home *** CD-ROM | disk | FTP | other *** search
/ Software Vault: The Gold Collection / Software Vault - The Gold Collection (American Databankers) (1993).ISO / cdr47 / ucrasm27.zip / STDLIB.TXT < prev    next >
Text File  |  1993-04-01  |  242KB  |  7,380 lines

  1. ***************************************************************************
  2. ***************************************************************************
  3.  
  4.  
  5.  
  6. The UCR Standard Library for Assembly Language Programmers,
  7. Written By Randall Hyde and others, is
  8.  
  9.   sssssss      ss     ss       ss       sssssss     sssssss
  10.   ss           ss     ss      ssss      ss    ss    ss
  11.   ss           ss     ss     ss  ss     ss    ss    ss
  12.   sssssss      sssssssss    ssssssss    sssssss     sssss        ssssssss
  13.        ss      ss     ss    ss    ss    ss  ss      ss
  14.        ss      ss     ss    ss    ss    ss   ss     ss
  15.   sssssss      ss     ss    ss    ss    ss    ss    sssssss
  16.  
  17.  
  18.  
  19.   ww                  ww       ww       sssssss     sssssss
  20.    ww                ww       wwww      ss    ss    ss
  21.     ww      ww      ww       ww  ww     ss    ss    ss
  22.      ww    wwww    ww       wwwwwwww    sssssss     sssss
  23.       ww  ww  ww  ww        ww    ww    ss  ss      ss
  24.        wwww    wwww         ww    ww    ss   ss     ss
  25.         ww      ww          ww    ww    ss    ss    sssssss
  26.  
  27.  
  28.  
  29.  
  30. We do not want any registration fees for this software.
  31.  
  32. Now for the catch...  It is more blessed to give than to receive.  
  33. If this software saves you time and effort and you enjoy using it, 
  34. our lives will be enriched knowing that others have appreciated our work.  
  35. We would like to share this wonderful feeling with you.  If you like this 
  36. software and use it, we would like you to contribute at least one routine to 
  37. the library.  Perhaps you think this library has some neat-o routines in it.  
  38. Imagine how nice it would become if everyone used their imagination to 
  39. contribute something useful to it.
  40.  
  41. We hereby release this software to the public domain.  You can use it in any
  42. way you see fit.  However, we would appreciate it if you share this software 
  43. with others as much as it has been shared it with you.  That is not to suggest
  44. that you give away software you have written with this package (We're not 
  45. quite as crazy as Richard Stallman, bless his heart), but if someone else would 
  46. like a copy of this library, please help them out.  Naturally, we would be 
  47. tickeled pink to receive credit in software that uses these routines (which is 
  48. the honorable thing to do) but we understand the way many corporations operate 
  49. and won't be terribly put off if you use it without giving due credit.  
  50.  
  51. Enjoy!
  52.  
  53. If you have comments, bug reports, new code to contribute, etc., you can 
  54. reach us through:
  55.  
  56.         rhyde                (On BIX).
  57.         rhyde@ucrmath.ucr.edu        (On Internet).
  58.         rhyde@ucrengr.ucr.edu
  59.  
  60. or
  61.  
  62.         Randall Hyde
  63.         Dept of Computer Science
  64.         122 University Office Bldg
  65.         University of California
  66.         Riverside, Ca. 92521
  67.  
  68.  
  69. COMMENTS ABOUT THE CODE:
  70. ************************
  71.  
  72. Please don't expect super optimal code here.  Most of it is fairly mediocre
  73. (from a size/speed point of view).  Hopefully, you'll agree, it's the idea
  74. that counts.  If you do not like something I have done, you have got the
  75. sources -- have at it.  (Of course, it would be appreciated if you would
  76. send any modifications to one of the E-MAIL addresses above.)
  77.  
  78.  
  79. ****************+******************** NOTE ************************************
  80.  
  81. Please understand the purpose of this code!  This library is here to make
  82. assembly language programming easy.  The nature of this library encourages
  83. people to write code in a fashion similar to that employed when they write
  84. programs in a high level language like C.  While this familiar style of
  85. programming does make the task easier, it is not the most appropriate
  86. approach to use when flat-out performance is what you're seeking.  "C code
  87. written with MOV instructions" is never as fast as pure assembly language
  88. code employing the proper programming paradigm.  Why mention this?  Well,
  89. some readers may have heard about assembly language's legendary performance
  90. and they're expecting to achieve that using this library.  While programs
  91. written with this library may very well run faster than a comparable program
  92. written in a HLL, you will not get fantastic performance improvement until
  93. you stop thinking in HLLs and starting "thinking" in assembly.  The purpose
  94. of this library is to help you *avoid* thinking in assembly language.  There-
  95. fore, this code will not help you achieve those fantastic performance levels
  96. you've been hearing about; indeed, this library may stand in the way of that
  97. goal.  It's not that these routines are terribly slow, mind you.  They just
  98. encourage an inappropriate programming style if speed is what you're after.
  99.  
  100. On the other hand, since only 10-20% of the code of any given program
  101. represents the time critical stuff (an argument long employed by HLL
  102. supporters), there is nothing wrong with judicious use of this code within
  103. a program that has to be fast.  As usual, if performance is your primary
  104. goal, you must study the problem and the program you generate very carefully
  105. to isolate the time critical portions.  If you are interested in high-
  106. performance programming at the "micro-algorithm" level, you should take a look
  107. at Michael Abrash's text "Zen of Assembly."  This excellent book will explain
  108. many ways to improve the performance of your code at the sub-algorithm level
  109. (where assembly language really shines).
  110.  
  111.  
  112.  
  113. COMMENTS ABOUT THIS DOCUMENTATION:
  114. **********************************
  115.  
  116. You will have to forgive us for the inconsistent style appearing throughout
  117. this document.  Keep in mind that this document has been prepared by many
  118. different people.  Keeping the styles consistent is a time consuming and
  119. difficult task.
  120.  
  121. Whenever a routine's description claims that the flags are not affected,
  122. you should not interpret this to mean that the routine preserves the flags.
  123. Most routines do *not* preserve any of the flags.  Such a statement simply
  124. means that the routine does not *explicitly* return a value in one (or more)
  125. of the flag bits.
  126.  
  127. Note that proper credit has been given to the author of each of the various
  128. routines appearing in this library *except* for those written by Randall
  129. Hyde.  All routines without an author by-line were probably written by
  130. Randall Hyde (unless we screwed up somewhere and forgot to put a name
  131. in the documentation).  Most of these routines were tested and documented
  132. by various students in Randy Hyde's CS 13 (assembly language) and CS 191X /
  133. CS 185 courses (Commercial Software Development).  There are too many names
  134. to mention here, but these students definitely deserve the credit for locating
  135. numerous bugs in the code, providing many suggestions, and doing other work.
  136.  
  137. Of course, there have been numerous suggestions and bug notices from helpful
  138. souls on BIX and the Internet, as well.  Thank you all.
  139.  
  140.  
  141. =============================================================================
  142.  
  143. Version History:
  144.  
  145. Version 00-     Initial release as "Randy Hyde's Standard Library for 80x86
  146.         Assembly Language programmers"
  147.  
  148. Version 10-    Initial release as "UCR Standard Library..."  CS 191X
  149.         students did some testing and documentation in this release.
  150.  
  151. Version 20-    More testing on several routines.  Added floating point
  152.         library and several other routines.
  153.  
  154. Version 21-    Fixed *MAJOR* bugs in floating point package.  Added
  155. 11-1-91        several new routines.  Included new "TEST" files with
  156.         the library.  Also included SHELL.ASM file inadvertently
  157.         left out of Version 2.0.
  158.  
  159. Version 22-    Made some minor modifications to puth, putl, ltoa, and htoa
  160. 11-14-91    as per suggestions made by David Holm and Terje Maithesen
  161.  
  162. Version 23-    Made a small but *major* modification to the stdlib.a and
  163. 11-22-91    stdlib.a6 files to force library calls into the STDGRP group.
  164.         Otherwise the linker substitued bad segment addresses for
  165.         the far calls to the library routines.  A real problem when
  166.         accessing variables in StdData.
  167.  
  168. Version 24-    Yet more changes to fix the stupid MASM group/segment:offset
  169. 12-7-91        bug.  Made various changes to the STDLIB.A file.  Also fixed
  170.         a problem in the FP routines- forgot to declare sl_sefpa
  171.         public.  Finally, created batch file to automatically unpack
  172.         everything from DOS (assuming presence of PKUNZIP somewhere
  173.         in the current path).
  174.  
  175. Version 25-    Some new macros (DOS, ExitPgm), fixed a problem with the
  176. 12-25-91    PUTI routine, added some SmartArray items.  Also added the
  177.         GetEnv routine.
  178.  
  179. Version 26-    Maintenance release coinciding with the Dr. Dobb's article
  180. 2/20/92        in the March 1992 issue.
  181.  
  182. Version 27-    SmartLists and interrupt driven serial routines added to
  183. 6/19/92        the libraries.  Also created smaller include files for
  184.         each of the standard library categories. (note: the serial
  185.         routines actually existed prior to this release, they were
  186.         cleaned up and documented for this release).  Fixed a couple
  187.         of truly disgusting bugs in the floating point package
  188.         (wouldn't properly print values like 8100 and hung whenever
  189.         encountering a zero value in FADD/FSUB).
  190.  
  191.  
  192. ==============================================================================
  193.  
  194.  
  195. ROUTINES WE WOULD LIKE TO HAVE:
  196. *******************************
  197.  
  198. If you're interested in adding some routines to this
  199. package, GREAT!  Here are some suggestions.
  200.  
  201. 1) Routines which manipulate directories (read/write/etc.)
  202. 2) A regular expression interpreter.
  203. 3) Length-prefixed strings package.
  204. 4) A graphics package.
  205. 5) An object-oriented programming class library.
  206. 6) Floating point functions (e.g., SIN, COS, etc.)
  207. 7) Just about anything else appearing in a HLL "standard" library.
  208. If you've got any ideas, we would  love to discuss them with you.  The best
  209. way to reach us is through the E-MAIL addresses above.
  210.  
  211.  
  212. MISSING ROUTINES TO BE SUPPLIED IN THE FUTURE:
  213. **********************************************
  214.  
  215. Character strings:
  216. trim-        Removes trailing blanks from a string.
  217. blkdel-        Removes leading blanks from a string.
  218. translit-    Transliterates characters in a string based on a translation
  219.         table.
  220.  
  221.  
  222. Pattern matching and character sets:
  223. span-        Skips through a sequence of characters in a string which
  224.         belong to a character set.
  225. break-        Skips through a sequence of characters in a string which do not
  226.         belong to a character set.
  227. any-        Skips over a character if it is a member of a set.
  228. notany-        Skips over a character in a string if it is not a member
  229.         of a set.
  230. skip-        Skips "n" characters in the string.
  231. tab-        Matches up to the nth character in a string.
  232. rtab-        Matches up to the nth character from the end of a string.
  233. pos-        Matches if we are currently at the nth position in a string.
  234. rpos-        Matches if we are at the nth position from the end of the
  235.         string.
  236. mark-        Marks a position in a string during pattern matching
  237. grab-        Copies everything from the last mark and creates a new string
  238.         on the stack from this substring.
  239. match-        Initialize pattern matching system.
  240. alternate-    Try an alternative if the current pattern does not match.
  241. arb-        Skip over an arbitrary number of characters in a match.
  242. replace-    Replace a substring from the last mark to the current
  243.         position with some other string.
  244. fail-        Force a match failure.
  245. succeed-    Force a match success.
  246.  
  247.  
  248.     Memory Manager Package
  249. Memavail-    Largest block of free memory available on the heap.
  250. Memfree-    Total amount of free space on the heap.
  251. BlockSize-    Returns the size of the memory block which es:di points at.
  252.  
  253.  
  254.     Process Manager Package
  255. CoCall-        Call a coroutine.
  256. CoInit-        Initialize a coroutine.
  257. CoRet-        Quit a coroutine.
  258.  
  259.  
  260. HOW TO USE THE STANDARD LIBRARY:
  261. ********************************
  262.  
  263. When you are ready to begin programming with the library, you should
  264. copy the shell.asm file, provided in the package, to another file in
  265. which you will be working, i.e. myprog.asm.  The shell.asm file sets
  266. up the machine (segments, etc.) as the UCR Standard Library expects
  267. them.  Results are undefined for other setups.  Therefore, I strongly
  268. suggest, that when you begin using these routines, you follow the
  269. shell.asm format.  Later, when you are familiar with the software,
  270. you may wish to create your own shell.asm file, but it is wise to
  271. initially use the one provided.  The shell.asm file has comments which
  272. tell you where to place your code, variables, etc.
  273.  
  274. There is an include file stdlib.a which
  275. you should include in every assembly you perform which calls the stdlib
  276. routines.  SHELL.ASM already includes this file.  *YOU MUST PLACE THE
  277. INCLUDE STATEMENT OUTSIDE OF ANY SEGMENTS IN YOUR PROGRAM*.  Preferably
  278. as the first line of your program (just like SHELL.ASM).  If you place
  279. this include directive inside a segment, certain assemblers/linkers
  280. (especially MASM) will not properly assemble and link your programs.
  281. They will assemble and link without error, but the resulting program
  282. will not execute correctly.
  283.  
  284. The STDLIB.A file contains macros you can use to call each of the routines
  285. in the standard library.  For example, to call PRINTF you would use the
  286. statement
  287.         printf
  288.         db    "format string",0
  289.         db    other,vars
  290.  
  291. rather than "calling" printf.  Printf is actually a macro, you cannot call
  292. it directly (all of the standard library routines have names like "sl_printf"
  293. and the macro issues a call to the appropriate routine).  These macros have
  294. two main purposes-- first, the differentiate calls to the standard library
  295. routines (i.e., no "call" instruction is the difference); and second, they
  296. contain some extra code to perform "smart linking" with MASM 5.1 & earlier,
  297. TASM, and OPTASM.  MASM 6.0 supports a new directive, extrndef, which
  298. eliminates the need for this extra code, but the extra code works nonetheless.
  299.  
  300. Starting with version 27, many of the standard library macros were separated
  301. into smaller files.  This speeds up assembly when you don't need *all* of
  302. the routines in the library (the macro file is getting quite large).
  303. STDLIB.A still exists and still loads everything, but you should get in the
  304. habit of specifying the smaller files instead.
  305.  
  306.  
  307. All of the standard library routines, and most of their local data values,
  308. are in a segment named "stdlib".  You should not create such a segment unless
  309. you plan on adding new routines to the standard library.
  310.  
  311.  
  312. HOW THE STANDARD LIBRARY IS ORGANIZED:
  313. **************************************
  314.  
  315. In the next several pages are the documentation spec sheets for each of the
  316. standard library routines.  The routines are listed by category.  The listing
  317. of the categories and their order in the documentation is below.
  318.  
  319.     Standard Input Routines
  320.     Standard Output Routines
  321.     Conversion Routines
  322.     Utility Routines
  323.     String Handling Routines
  324.     Memory Management Routines
  325.     Character Set Routines
  326.     Floating Point Routines
  327.     File I/O
  328.     Miscellaneous Routines
  329.     Smart List Routines
  330.     Serial Port I/O
  331.  
  332. In addition, at the beginning of each of the category is a brief
  333. discussion of the purpose of its routines.
  334.  
  335.  
  336.  
  337.  
  338.  
  339. Standard Input Routines:
  340. Character Input Routines
  341. ------------------------
  342.  
  343.  
  344.     The character input routines take input from either a standard
  345. device (keyboard, etc.) or a standard library.  After the character input
  346. routines receive the characters they either place the characters on the stack
  347. and/or return.  The character input routines work similar to the "C" character
  348. input routines.
  349.  
  350.  
  351.  
  352. Routine:  Getc
  353. --------------
  354.  
  355.  
  356. Category:             Character Input Routine
  357.  
  358.  
  359. Registers on Entry:   None
  360.  
  361.  
  362. Registers on Return:  AL- Character from input device.
  363.                       AH- 0 if eof, 1 if not eof.
  364.  
  365.  
  366. Flags Affected:       Carry- 0 if no error, 1 if error.  If error occurs, AX
  367.                              contains DOS error code.
  368.  
  369.  
  370. Example of Usage:  
  371.                       getc
  372.                       mov     KbdChar, al
  373.                       putc
  374.  
  375.  
  376. Description:  This routine reads a character from the standard input device.
  377.               This call is synchronous, that is, it does not return until a
  378.               character is available.  The Default input device is DOS
  379.               standard input.
  380.  
  381.               Getc returns two types of values: extended ASCII (codes 1-255)
  382.               and IBM keyboard scan codes.  If Getc returns a non-zero value,
  383.               you may interpret this value as an ASCII character.  If Getc
  384.               returns zero, you must call Getc again to get the actual
  385.               keypress.
  386.  
  387.               The second call returns an IBM PC keyboard scan code.
  388.  
  389.               Since the user may redirect input from the DOS command line,
  390.               there is the possibility of encountering end-of-file (eof)
  391.               when calling getc.  Getc uses the AH register to return eof
  392.               status.  AH contains the number of characters actually read
  393.               from the standard input device.  If it returns one, then
  394.               you've got a valid character.  If it returns zero, you've
  395.               reached end of file.  Note that pressing control-z forces an
  396.               end of file condition when reading data from the keyboard.
  397.  
  398.               This routine returns the carry flag clear if the operation
  399.               was successful.  It returns the carry flag set if some sort
  400.               of error occurred while reading the character.  Note that eof
  401.               is not an error condition.  Upon reaching the end of file,
  402.               Getc returns with the carry flag clear.  If getc is seen from
  403.               a file the control-z is not seen as an end-of-file marker,
  404.               but just read in as a character of the file.
  405.  
  406.               Control-c if read from a keyboard device aborts the program.
  407.               However if when reading something other than a keyboard
  408.           (files, serial ports), control-c from the input source
  409.               returns control-c.  However when pressing control-break
  410.               the program will abort regardless of the input source.
  411.  
  412.               Regarding CR/LF, if the input is from a device, (eg. keyboard
  413.               serial port) getc returns whatever that device driver returns,
  414.               (generally CR without a LF).  However if the input is from
  415.               a file, getc stripes a single LF if it immediately follows
  416.               the CR.
  417.  
  418.               When using getc files operate in "cooked" mode.  While
  419.               devices operate in "pseudo-cooked" mode, which means no
  420.               buffering, no CR -> CR/LF, but it handles control-c, and
  421.               control-z.
  422.  
  423.           See the sources for more information about GETC's internal
  424.           operation.
  425.  
  426. Include:    stdlib.a or stdin.a
  427.  
  428.  
  429.  
  430.  
  431. Routine:   GetcStdIn
  432. --------------------
  433.  
  434.  
  435. Category:             Character Input Routine
  436.  
  437. Register on entry:    None.
  438.  
  439. Register on return:   AL- Character from input device.
  440.  
  441. Flags affected:       AH- 0 if eof, 1 if not eof.
  442.                       Carry- 0 if no error, 1 if error
  443.                       (AX contains DOS error code if error occurs).
  444.  
  445.  
  446. Example of Usage:
  447.                       GetcStdIn
  448.                       mov     InputChr, al
  449.                       putc
  450.  
  451.  
  452. Description:    This routine reads a character from the DOS standard input
  453.                 device.  This call is synchronous, that is, it does not return
  454.                 until a character is available.  See the description of Getc
  455.                 above for more details.
  456.  
  457.         The difference between Getc and GetcStdIn is that your
  458.         program can redirect Getc using other calls in this library.
  459.         GetcStdIn calls DOS directly without going through this
  460.         redirection mechanism.
  461.  
  462.  
  463. Include:        stdlib.a or stdin.a
  464.  
  465.  
  466.  
  467.  
  468.  
  469.  
  470. Routine:   GetcBIOS
  471. -------------------
  472.  
  473.  
  474. Category:             Character Input Routine
  475.  
  476. Register on entry:    None
  477.  
  478. Register on return:   AL- Character from the keyboard.
  479.  
  480. Flags affected:       AH- 1 (always).  Carry- 0 (always).
  481.  
  482. Example of Usage:   
  483.               GetcBIOS
  484.                       mov     CharRead, al
  485.                       putc
  486.  
  487.  
  488. Description:   This routine reads a character from the keyboard.  This call is
  489.                synchronous, that is it does not return until a character is
  490.                available.
  491.  
  492.         Note that there is no special character processing.  This
  493.         code does *not* check for EOF, control-C, or anything
  494.         else like that.
  495.  
  496.  
  497.  
  498. Include:        stdlib.a or stdin.a
  499.  
  500.  
  501.  
  502. Routine:  SetInAdrs
  503. -------------------
  504.  
  505. Category:               Character Input Routine
  506.  
  507. Registers on Entry:     ES:DI - address of new input routine
  508.  
  509. Registers on return:    None 
  510.  
  511. Flags affected:
  512.  
  513. Examples of Usage:
  514.  
  515.                         mov     es, seg NewInputRoutine
  516.                         mov     di, offset NewInputRoutine
  517.                         SetInAdrs
  518.  
  519.  
  520.  
  521.                         les     di, RoutinePtr
  522.                         SetInAdrs
  523.  
  524.  
  525. Description:    This routine redirects the stdlib standard input so that it 
  526.                 calls the routine who's address you pass in es:di.  The
  527.         routine (whose address appears in es:di) should be a "getc"
  528.         routine which reads a character from somewhere and returns
  529.         that character in AL.  It should also return EOF status in
  530.         the AH register and error status in the carry flag (see
  531.         the description of GETC for more details).
  532.  
  533.  
  534. Include:                stdlib.a or stdin.a
  535.  
  536.  
  537.  
  538.  
  539.  
  540. Routine:   GetInAdrs
  541. --------------------
  542.  
  543. Category:             Character Input Routine
  544.  
  545. Register on entry:    None
  546.  
  547. Register on return:   ES:DI - address of current input routine (called by Getc).
  548.  
  549. Flags affected:       None
  550.  
  551.  
  552. Example of Usage:   
  553.                       GetInAdrs
  554.               mov     word ptr SaveInAdrs, di
  555.               mov     word ptr SaveInAdrs+2, es
  556.  
  557.  
  558. Description:   You can use this function to get the address of the current
  559.            input routine, perhaps so you can save it or see if it is
  560.            currently pointing at some particular piece of code.
  561.            If you want to temporarily redirect the input and then restore
  562.            the original input or outline, consider using
  563.            PushInAdrs/PopInAdrs described later.
  564.  
  565.  
  566. Include:        stdlib.a or stdin.a
  567.  
  568.  
  569.  
  570. Routine:   PushInAdrs
  571. ---------------------
  572.  
  573. Category:             Character Input Routine
  574.  
  575. Register on entry:    ES:DI - Address of new input routine.
  576.  
  577. Register on return:   Carry=0 if operation successful.
  578.                       Carry=1 if there were already 16 items on the stack.
  579.                          
  580. Example of Usage:   
  581.                       mov     es, seg NewInputRoutine
  582.                       mov     di, offset NewInputRoutine
  583.                       PushInAdrs
  584.                         .
  585.                         .
  586.                         .
  587.                       les     di, RoutinePtr
  588.                       PushInAdrs
  589.  
  590.  
  591. Description:   This routine "pushes" the current input address onto an
  592.                internal stack and then copies the value in es:di into the
  593.                current input routine pointer.  The PushInAdrs and PopInAdrs
  594.                routines let you easily save and redirect the standard output
  595.                and then restore the original output routine address later on.
  596.                If you attempt to push more than 16 items on the stack,
  597.                PushInAdrs will ignore your request and return with the
  598.                carry flag set.  If PushInAdrs is successful, it will
  599.                return with the carry flag clear.
  600.  
  601.  
  602. Include:    stdlib.a or stdin.a
  603.  
  604.  
  605.  
  606.  
  607.  
  608. Routine:   PopInAdrs
  609. --------------------
  610.  
  611. Category:             Character Input Routine
  612.  
  613. Register on entry:    None
  614.  
  615. Register on return:   ES:DI - Points at the previous stdout routine before
  616.                       the pop.
  617.  
  618. Example of Usage:   
  619.                       mov     es, seg NewInRoutine
  620.                       mov     di, offset NewInputRoutine
  621.                       PushInAdrs
  622.                         .
  623.                         .
  624.                         .
  625.                       PopInAdrs
  626.  
  627.  
  628. Description:   PopInAdrs undoes the effects of PushInAdrs.  It pops an item
  629.                off the internal stack and stores it into the input routine
  630.                pointer.  The previous value in the output pointer is returned
  631.                in es:di.
  632.  
  633. Include:    stdlib.a or stdin.a
  634.  
  635.  
  636.  
  637.  
  638.  
  639. Routine:  Gets, Getsm
  640. ---------------------
  641.  
  642. Category:             Character Input Routine
  643.  
  644. Register on entry:    ES:DI- Pointer to input buffer (gets only).
  645.  
  646. Register on return:   ES:DI - address of input of text.
  647.                       carry-  0 if no error, 1 if error.
  648.                       If error, AX contains: 0- End of
  649.                       file encountered in middle of
  650.                       string.  1- Memory allocation error (getsm only).
  651.                       Other- DOS error code.
  652.  
  653.  
  654. Flags affected:       None
  655.  
  656. Example of usage:    
  657.                       getsm           ;Read a string from the
  658.                                       ;keyboard
  659.                       puts            ;Print it
  660.                       putcr           ;Print a new line
  661.                       free            ;Deallocate storage for
  662.                                       ;string.
  663.  
  664.               mov    di, seg buffer
  665.               mov    es, di
  666.               lea    di, buffer
  667.               gets
  668.               puts
  669.               putcr
  670.  
  671.  
  672. Description:       Reads a line of text from the stdlib standard input device.
  673.         You must pass a pointer to the recipient buffer in es:di to
  674.         the GETS routine.  GETSM automatically allocates storage for
  675.         the string on the heap (up to 256 bytes) and returns a pointer
  676.         to this block in es:di.
  677.  
  678.         Gets(m) returns all characters typed by the user except for the
  679.         carriage return (ENTER) key code.  These routines return a
  680.         zero-terminated string (with es:di pointing at the string).
  681.         Exactly how Gets(m) treats the incoming data depends upon
  682.         the source device, however, you can usually count on Gets(m)
  683.         properly handling backspace (erases previous character),
  684.         escape (erase entire line), and ENTER (accept current line).
  685.  
  686.         Other keys may affect Gets(m) as well.  For example, Gets(m),
  687.         by default, calls Getc which, in turn, usually calls DOS'
  688.         standard input routine.  If you type control-C or break while
  689.         read from DOS' standard input it may abort the program.
  690.  
  691.         If an error occurs during input (e.g., EOF encountered in
  692.         the middle of a line) Gets(m) returns the error code in
  693.         AX.  If no error occurs, Gets(m) preserves AX.
  694.  
  695. Include:                  stdlib.a or stdin.a
  696.  
  697.  
  698.  
  699.  
  700.  
  701. Routine:  Scanf
  702. ---------------
  703.  
  704. Category:             Character Input Routine
  705.  
  706. Register on entry:    None
  707.  
  708. Register on return:   None
  709.  
  710. Flags affected:       None
  711.  
  712. Example of usage:   
  713.                       scanf
  714.                       db      "%i  %h  %^s",0
  715.                       dd      i, x, sptr
  716.  
  717. Description:   * Formatted input from stdlib standard input.
  718.                * Similar to C's scanf routine.
  719.                * Converts ASCII to integer, unsigned, character, string, hex,
  720.                  and long values of the above.
  721.                Scanf provides formatted input in a fashion analogous to
  722.                printf's output facilities.  Actually, it turns out that scanf
  723.                is considerably less useful than printf because it doesn't
  724.                provide reasonable error checking facilities (neither does C's
  725.                version of this routine).  But for quick and dirty programs 
  726.                whose input can be controlled in a rigid fashion (or if you're
  727.                willing to live by "garbage in, garbage out")  scanf provides 
  728.                a convenient way to get input from the user.  Like printf, the
  729.                scanf routine expects you to follow the call with a format 
  730.                string and then a list of (far pointer) memory addresses.  The
  731.                items in the scanf format string take the following form: %^f,
  732.                where f represents d, i, x, h, u, c, x, ld, li, lx, or lu.  
  733.                Like printf, the "^" symbol tells scanf that the address
  734.                following the format string is the address of a (far) pointer
  735.                to the data rather than the address of the data location itself.
  736.                By default, scanf automatically skips any leading whitespace 
  737.                before attempting to read a numeric value.  You can instruct
  738.                scanf to skip other characters by placing that character in the
  739.                format string.  For example, the following call instructs scanf
  740.                to read three integers separated by commas (and/or whitespace):
  741.  
  742.                                  scanf  
  743.                   db                "%i,%i,%i",0
  744.                               dd                 i1,i2,i3
  745.  
  746.                Whenever scanf encounters a non-blank character in the format
  747.                string, it will skip that character (including multiple
  748.                occurrences of that character) if it appears next in the input
  749.                stream.  Scanf always calls gets to read a new line of text 
  750.                from stdlib's standard input.  If scanf exhausts the format 
  751.                list, it ignores any remaining characters on the line.  If
  752.                scanf exhausts the input line before processing all of the
  753.                format items, it leaves the remaining variables unchanged.
  754.                Scanf always deallocates the storage allocated by gets.
  755.  
  756.  
  757. Include:                stdlib.a or stdin.a
  758.  
  759.  
  760.  
  761.  
  762. Character Output Routines
  763. -------------------------
  764.  
  765.  
  766. The stdlib character output routines allow you to print to the 
  767. standard output device.  Although the processing of non-ASCII 
  768. characters is undefined, most output devices handle these characters
  769. properly.  In particular, they can handle return, line feed, back space, 
  770. and tab.  
  771.  
  772. Most of the output routines in the standard library output data 
  773. through the Putc routine.  They generally use the AX register upon 
  774. entry and print the character(s) to the standard output device by
  775. calling DOS by default. The  output is redirectable to the 
  776. user-written routine.  However, the PutcBIOS routine prints doesn't 
  777. use DOS.  Instead it uses BIOS routines to print the character in AL 
  778. using the INT command for teletype-like output. 
  779.  
  780. The print routines are similar to those in C, however, they differ
  781. in their implementation. The print routine returns to the address
  782. immediately following the terminating byte, therefore, it is important
  783. to remember to terminate your string with zero or you will print an 
  784. unexpected sequence of characters.
  785.  
  786.  
  787.  
  788. Routine:  Putc
  789. --------------
  790.  
  791. Category:             Character Output Routine
  792.  
  793. Registers on Entry:   AL- character to output
  794.  
  795. Registers on Return:  None
  796.  
  797. Flags affected:       None
  798.  
  799. Example of Usage:
  800.                        mov     al, 'C'
  801.                        putc                    ;Prints "C" to std output.
  802.  
  803.  
  804. Description:  Putc is the primitive character output routine.  Most other
  805.               output routines in the standard library output data through
  806.               this procedure.  It prints the ASCII character in AL register.  
  807.               The processing of control codes is undefined although most output
  808.               routines this routine links to should be able to handle return, 
  809.               line feed, back space, and tab.  By default, this routine calls
  810.               DOS to print the character to the standard output device.  The
  811.               output is redirectable to to user-written routine.
  812.  
  813.  
  814. Include:                stdlib.a or stdout.a
  815.  
  816.  
  817.  
  818. Routine:  PutCR
  819. ---------------
  820.  
  821. Category:             Character Output Routine 
  822.  
  823. Register on entry:    None
  824.  
  825. Register on return:   None
  826.  
  827. Flags affected:       None
  828.  
  829. Example of Usage:     PutCR
  830.  
  831.  
  832. Description:  Using PutCR is an easy way of printing a newline to the stdlib 
  833.               standard output. It prints a newline (carriage return/line feed) 
  834.               to the current standard output device.
  835.  
  836.  
  837. Include:                stdlib.a or stdout.a
  838.  
  839.  
  840. Routine: PutcStdOut
  841. -------------------
  842.  
  843. Category:              Character Output Routine
  844.  
  845. Registers on Entry:    AL- character to output
  846.  
  847. Registers on Return:   None
  848.  
  849. Flags Affected:        None
  850.  
  851. Example of Usage:
  852.                        mov AL, 'C'
  853.                        PutcStdOut        ; Writes "C" to standard output
  854.  
  855.  
  856. Description:  PutcStdOut calls DOS to print the character in AL to the standard
  857.               output device.  Although processing of non-ASCII characters and
  858.               control characters is undefined, most output devices handle these
  859.               characters properly.  In particular, most output devices properly
  860.               handle return, line feed, back space, and tab.  The output is
  861.               redirectable via DOS I/O redirection.
  862.  
  863.  
  864. Include:                stdlib.a or stdout.a
  865.  
  866.  
  867.  
  868. Routine: PutcBIOS
  869. -----------------
  870.  
  871. Category:              Character Output Routine
  872.  
  873. Registers on Entry:    AL- character to print
  874.  
  875. Registers on Return:   None
  876.  
  877. Flags Affected:        None
  878.  
  879. Example of Usage:
  880.                        mov AL, "C"
  881.                        PutcBIOS
  882.  
  883.  
  884. Description:  PutcBIOS prints the character in AL using the BIOS routines,
  885.               using INT 10H/AH=14 for teletype-like output.  Output through
  886.               this routine cannot be redirected; such output is always sent
  887.               to the video display on the PC (unless, of course, someone has
  888.               patched INT 10h).  Handles return, line feed, back space, and
  889.               tab.  Prints other control characters using the IBM Character
  890.           set.
  891.  
  892.  
  893. Include:         stdlib.a or stdout.a
  894.  
  895.  
  896.  
  897. Routine: GetOutAdrs
  898. -------------------
  899.  
  900. Category:             Character Output Routine
  901.  
  902. Registers on Entry:   None
  903.  
  904. Registers on Return:  ES:DI- address of current output routine (called by Putc)
  905.  
  906. Flags Affected:       None
  907.  
  908. Example of Usage: 
  909.                       GetOutAdrs
  910.                       mov word ptr SaveOutAdrs, DI
  911.                       mov word ptr SaveOutAdrs+2, ES
  912.  
  913. Description:  GetOutAdrs gets the address of the current output routine, perhaps
  914.               so you can save it or see if it is currently pointing at some
  915.               particular piece of code.  If you want to temporarily redirect
  916.               the output and then restore the original output routine, consider
  917.               using PushOutAdrs/PopOutAdrs described later.
  918.  
  919. Include:    stdlib.a or stdout.a
  920.  
  921.  
  922.  
  923.  
  924. Routine:  SetOutAdrs
  925. --------------------
  926.  
  927. Category:               Character Output Routine
  928.  
  929. Registers on Entry:     ES:DI - address of new output routine
  930.  
  931. Registers on return:    None 
  932.  
  933. Flags affected:         None
  934.  
  935. Example of Usage:
  936.  
  937.                         mov     es, seg NewOutputRoutine
  938.                         mov     di, offset NewOutputRoutine
  939.                         SetOutAdrs
  940.                         les     di, RoutinePtr
  941.                         SetOutAdrs
  942.  
  943. Description:  This routine redirects the stdlib standard output so that it
  944.               calls the routine who's address you pass in es:di.  This routine
  945.               expects the character to be in AL and must preserve all registers.
  946.               It handles the printable ASCII characters and the four control
  947.               characters return, line feed, back space, and tab.  (The routine
  948.               may be modified in the case that you wish to handle these codes
  949.               in a different fashion.)
  950.  
  951.  
  952. Include:        stdlib.a or stdout.a
  953.  
  954.  
  955. Routine:  PushOutAdrs
  956. ---------------------
  957.  
  958. Category:              Character Output Routine 
  959.  
  960. Registers on Entry:    ES:DI- Address of new output routine
  961.  
  962. Registers on Return:   None
  963.  
  964. Flags Affected:        Carry = 0 if operation is successful
  965.                        Carry = 1 if there were already 16 items on the stack
  966.  
  967. Example of Usage:  
  968.                        mov  ES, seg NewOutputRoutine
  969.                        mov  DI, offset NewOutputRoutine
  970.                        PushOutAdrs
  971.                           .
  972.                           .
  973.                           . 
  974.                        les  DI, RoutinePtr
  975.                        PushOutAdrs
  976.  
  977.  
  978. Description:  This routine "pushes" the current output address onto an internal
  979.               stack and then uses the value in es:di as the current output
  980.               routine address.  The PushOutAdrs and PopOutAdrs routines let you
  981.               easily save and redirect the standard output and then restore the
  982.               original output routine address later on.  If you attempt to push
  983.               more than 16 items on the stack, PushOutAdrs will ignore your
  984.               request and return with the carry flag set.  If PushOutAdrs is
  985.               successful, it will return with the carry flag clear.
  986.  
  987.  
  988. Include:          stdlib.a or stdout.a
  989.  
  990.  
  991.  
  992. Routine:  PopOutAdrs
  993. --------------------
  994.  
  995. Category:             Character Output Routine 
  996.  
  997. Registers on Entry:   None
  998.  
  999. Registers on Return:  ES:DI- Points at the previous stdout routine before
  1000.                       the pop
  1001.  
  1002. Flags Affected:       None
  1003.  
  1004. Example of Usage:  
  1005.                       mov ES, seg NewOutputRoutine
  1006.                       mov DI, offset NewOutputRoutine
  1007.                       PushOutAdrs
  1008.                          .
  1009.                          .
  1010.                          .
  1011.                       PopOutAdrs
  1012.  
  1013.  
  1014. Description:  PopOutAdrs undoes the effects of PushOutAdrs.  It pops an item off
  1015.               the internal stack and stores it into the output routine pointer.
  1016.               The previous value in the output pointer is returned in es:di.
  1017.               Defaults to PutcStdOut if you attempt to pop too many items off
  1018.               the stack.
  1019.  
  1020. Include:    stdlib.a or stdout.a
  1021.  
  1022.  
  1023.  
  1024.  
  1025. Routine:  Puts
  1026. --------------
  1027.  
  1028. Category:            Character Output Routine 
  1029.  
  1030. Register on entry:   ES:DI register - contains the address of the string
  1031.  
  1032. Register on return:  None
  1033.  
  1034. Flags affected:      None
  1035.  
  1036. Example of Usage:
  1037.                      les     di, StrToPrt
  1038.                      puts
  1039.                      putcr
  1040.  
  1041.  
  1042. Description:   Puts prints a zero-terminated string whose address appears
  1043.                in es:di.  Each character appearing in the string is printed
  1044.                verbatim.  There are no special escape characters.  Unlike
  1045.                the "C" routine by the same name, puts does not print a
  1046.                newline after printing the string.  Use putcr if you want
  1047.                to print the newline after printing a string with puts.
  1048.  
  1049.  
  1050. Include:        stdlib.a or stdout.a
  1051.  
  1052.  
  1053.  
  1054. Routine:  Puth
  1055. --------------
  1056.  
  1057. Category:             Character Output Routine
  1058.  
  1059. Register on entry:    AL 
  1060.  
  1061. Register on return:   AL
  1062.  
  1063. Flags affected:       None
  1064.  
  1065. Example of Usage:
  1066.                       mov     al, 1fh
  1067.                       puth
  1068.  
  1069.  
  1070. Description:    The Puth routine Prints the value in the AL register as two
  1071.                 hexadecimal digits.  If the value in AL is between 0 and 0Fh, 
  1072.                 puth will print a leading zero.  This routine calls the stdlib
  1073.                 standard output routine (putc) to print all characters.
  1074.  
  1075.  
  1076. Include:        stdlib.a or stdout.a
  1077.  
  1078.  
  1079.  
  1080. Routine:  Putw
  1081. --------------
  1082.  
  1083. Category:             Character Output Routine
  1084.  
  1085. Registers on Entry:   AX- Value to print
  1086.  
  1087. Registers on Return:  None
  1088.  
  1089. Flags Affected:       None
  1090.  
  1091. Example of Usage: 
  1092.                       mov AX, 0f1fh
  1093.                       putw
  1094.  
  1095.  
  1096. Description:  The Putw routine prints the value in the AX register as four
  1097.               hexadecimal digits (including leading zeros if necessary).  
  1098.               This routine calls the stdlib standard output routine (putc) 
  1099.               to print all characters.
  1100.  
  1101. Include:        stdlib.a or stdout.a
  1102.  
  1103.  
  1104.  
  1105. Routine:  Puti
  1106. --------------
  1107.  
  1108. Category:             Character Output Routine
  1109.  
  1110. Registers on Entry:   AX- Value to print
  1111.  
  1112. Registers on Return:  None
  1113.  
  1114. Flags Affected:       None
  1115.  
  1116. Example of Usage: 
  1117.                       mov AX, -1234
  1118.                       puti
  1119.  
  1120.  
  1121. Description:  Puti prints the value in the AX register as a decimal integer.
  1122.               This routine uses the exact number of screen positions required
  1123.               to print the number (including a position for the minus sign, if
  1124.               the number is negative).  This routine calls the stdlib standard
  1125.               output routine (putc) to print all characters.
  1126.  
  1127.  
  1128. Include:        stdlib.a or stdout.a
  1129.  
  1130.  
  1131.  
  1132. Routine:  Putu
  1133. --------------
  1134.  
  1135. Category:             Character Output Routine
  1136.  
  1137. Register on entry:    AX- Unsigned value to print.
  1138.  
  1139. Register on return:   None
  1140.  
  1141. Flags affected:       None
  1142.  
  1143. Example of Usage:
  1144.                       mov     ax, 1234
  1145.                       putu
  1146.  
  1147.  
  1148. Description:  Putu prints the value in the AX register as an unsigned integer.
  1149.               This routine uses the exact number of screen positions required
  1150.               to print the number.  This routine calls the stdlib standard
  1151.               output routine (putc) to print all characters.
  1152.  
  1153.  
  1154. Include:        stdlib.a or stdout.a
  1155.  
  1156.  
  1157.  
  1158.  
  1159. Routine:  Putl
  1160. --------------
  1161.  
  1162. Category:            Character Output Routine
  1163.  
  1164. Register on entry:   DX:AX- Value to print
  1165.  
  1166. Register on return:  None
  1167.  
  1168. Flags affected:      None
  1169.  
  1170. Example of Usage:
  1171.                      mov     dx, 0ffffh
  1172.                      mov     ax, -1234
  1173.                      putl
  1174.  
  1175.  
  1176. Description:   Putl prints the value in the DX:AX registers as an integer.
  1177.                This routine uses the exact number of screen positions
  1178.                required to print the number (including a position for the
  1179.                minus sign, if the number is negative).  This routine calls
  1180.                the stdlib standard output routine (putc) to print all
  1181.                characters.
  1182.  
  1183.  
  1184. Include:        stdlib.a or stdout.a
  1185.  
  1186.  
  1187.  
  1188. Routine:  Putul
  1189. ---------------
  1190.  
  1191. Category:             Character Output Routine
  1192.  
  1193. Register on entry:    DX:AX register
  1194.  
  1195. Register on return:   None
  1196.  
  1197. Flags affected:       None
  1198.  
  1199. Example of Usage:
  1200.                       mov     dx, 12h
  1201.                       mov     ax, 1234
  1202.                       putul
  1203.  
  1204.  
  1205. Description:    Putul prints the value in the DX:AX registers as an unsigned
  1206.                 integer.  This routine uses the exact number of screen
  1207.                 positions required to print the number.  This routine calls 
  1208.         the stdlib standard output routine (putc) to print all
  1209.         characters.
  1210.  
  1211.  
  1212. Include:        stdlib.a or stdout.a
  1213.  
  1214.  
  1215. Routine:  PutISize
  1216. ------------------
  1217.  
  1218. Category:              Character Output Routine
  1219.  
  1220. Registers on Entry:    AX - Integer value to print
  1221.                        CX - Minimum number of print positions to use
  1222.  
  1223. Registers on return:   None 
  1224.  
  1225. Flags affected:
  1226.  
  1227. Example of Usage:
  1228.                        mov     cx, 5
  1229.                        mov     ax, I
  1230.                        PutISize
  1231.                            .
  1232.                            . 
  1233.                            .
  1234.                        mov     cx, 12
  1235.                        mov     ax, J
  1236.                        PutISize
  1237.  
  1238.  
  1239. Description:    PutISize prints the signed integer value in AX to the
  1240.                 stdlib standard output device using a minimum of n print
  1241.                 positions.  CX contains n, the minimum field width for the
  1242.                 output value.  The number (including any necessary minus sign)
  1243.                 is printed right justified in the output field.
  1244.                 If the number in AX requires more print positions than
  1245.                 specified by CX, PutISize uses however many print positions
  1246.                 are necessary to actually print the number.  If you specify
  1247.                 zero in CX, PutISize uses the minimum number of print positions
  1248.                 required.  Of course, PutI will also use the minimum number
  1249.                 of print positions without disturbing the value in the CX
  1250.                 register.
  1251.  
  1252.                 Note that, under no circumstances, will the number in AX
  1253.                 ever require more than 6 print positions (-32,767 requires
  1254.                 the most print positions).
  1255.  
  1256.  
  1257. Include:        stdlib.a or stdout.a
  1258.  
  1259.  
  1260.  
  1261. Routine:  PutUSize
  1262. ------------------
  1263.  
  1264. Category:              Character Output Routine
  1265.  
  1266. Registers on entry:    AX- Value to print
  1267.                CX- Minimum field width
  1268.  
  1269. Registers on return:   None
  1270.  
  1271. Flags affected:        None
  1272.  
  1273. Example of usage: 
  1274.                        mov     cx, 8
  1275.                        mov     ax, U
  1276.                        PutUSize
  1277.  
  1278.  
  1279. Description:  PutUSize prints the value in AX as an unsigned decimal integer.
  1280.               The minimum field width specified by the value in CX.
  1281.               Like PutISize above except this one prints unsigned values.  
  1282.               Note that the maximum number of print positions required by any 
  1283.               number (e.g., 65,535) is five.
  1284.  
  1285.  
  1286. Include:        stdlib.a or stdout.a
  1287.  
  1288.  
  1289.  
  1290. Routine:  PutLSize
  1291. ------------------
  1292.  
  1293. Category:            Character Output Routine
  1294.  
  1295. Register on entry:   DX:AX-32 bit value to print
  1296.              CX- Minimum field width
  1297.  
  1298. Register on return:  None
  1299.  
  1300. Flags affected:      None
  1301.  
  1302. Example of Usage:
  1303.                      mov     cx, 16
  1304.                      mov     dx, word ptr L+2
  1305.                      mov     ax, word ptr L
  1306.                      PutLSize
  1307.  
  1308.  
  1309. Description:   PutLSize is similar to PutISize, except this prints the long 
  1310.                integer value in DX:AX.  Note that there may be as many as 
  1311.                11 print positions (e.g., -1,000,000,000).
  1312.  
  1313. Include:        stdlib.a or stdout.a
  1314.  
  1315.  
  1316.  
  1317.  
  1318. Routine:  PutULSize
  1319. -------------------
  1320.  
  1321.  
  1322. Category:            Character Output Routine
  1323.  
  1324.  
  1325. Register on entry:   AX : DX and CX
  1326.  
  1327.  
  1328. Register on return:  None
  1329.  
  1330.  
  1331. Flags affected:      None
  1332.  
  1333.  
  1334. Example of usage:    mov     cx, 8
  1335.                      mov     dx, word ptr UL+2
  1336.                      mov     ax, word ptr UL
  1337.                      PutULSize
  1338.  
  1339.  
  1340. Description:  Prints the value in DX:AX as a long unsigned decimal integer.
  1341.               Prints the number in a minimum field width specified by the
  1342.               value in CX.  Just like PutLSize above except this one prints
  1343.               unsigned numbers rather than signed long integers.  The largest
  1344.               field width for such a value is 10 print positions.
  1345.  
  1346.  
  1347. Include:        stdlib.a or stdout.a
  1348.  
  1349.  
  1350. Routine:   Print
  1351. ----------------
  1352.  
  1353. Category:             Character Output Routine
  1354.  
  1355. Register on entry:    CS:RET - Return address points at the string to print.
  1356.  
  1357. Register on return:   None
  1358.  
  1359. Flags affected:       None
  1360.  
  1361. Examples of Usage:    print
  1362.                       db      "Print this string to the display device"
  1363.                       db      13,10
  1364.                       db      "This appears on a new line"
  1365.                       db      13,10
  1366.                       db      0
  1367.  
  1368.  
  1369. Description:   Print lets you print string literals in a convenient
  1370.                fashion.  The string to print immediately follows the call
  1371.                to the print routine.  The string must contain a
  1372.                zero terminating byte and may not contain any intervening
  1373.                zero bytes.  Since the print routine returns to the address
  1374.                immediately following the zero terminating byte, forgetting
  1375.                this byte or attempting to print a zero byte in the middle
  1376.                of a literal string will cause print to return to an
  1377.                unexpected instruction.  This usually hangs up the machine.
  1378.                Be very careful when using this routine!
  1379.  
  1380.  
  1381. Include:        stdlib.a or stdout.a
  1382.  
  1383.  
  1384. Routine:        Printf
  1385. ----------------------
  1386.  
  1387. Category:             Character Output Routine
  1388.  
  1389. Register on entry:    CS:RET - Return address points at the format string
  1390.  
  1391. Register on return:   None
  1392.  
  1393. Flags affected:       None
  1394.  
  1395. Example of Usage:
  1396.                       printf
  1397.                       db      "Indirect access to i: %^d",13,10,0
  1398.                       dd      IPtr;
  1399.                       printf
  1400.                       db      "A string allocated on the heap: %-\.32^s"
  1401.                       db      13,10,0
  1402.                       dd      SPtr
  1403.  
  1404.  
  1405.  
  1406. Descriptions:   Printf, like its "C" namesake, provides formatted output
  1407.                 capabilities for the stdlib package.  A typical call to printf
  1408.                 always takes the following form:
  1409.  
  1410.                         printf
  1411.                         db              "format string",0
  1412.                         dd              operand1, operand2, ..., operandn
  1413.  
  1414.                 The format string is comparable to the one provided in the
  1415.                 "C" programming language.  For most characters, printf simply
  1416.                 prints the characters in the format string up to the
  1417.                 terminating zero byte.  The two exceptions are characters
  1418.                 prefixed by a backslash ("\") and characters prefixed by a
  1419.                 percent sign ("%").  Like C's printf, stdlib's printf uses
  1420.                 the backslash as an escape character and the percent sign as
  1421.                 a lead-in to a format string.
  1422.  
  1423.                 Printf uses the escape character ("\") to print special
  1424.                 characters in a fashion similar to, but not identical to C's
  1425.                 printf.  Stdlib's printf routine supports the following
  1426.                 special characters:
  1427.  
  1428.                 *  r     Print a carriage return (but no line feed)
  1429.                 *  n     Print a new line character (carriage return/line feed).
  1430.                 *  b     Print a backspace character.
  1431.                 *  t     Print a tab character.
  1432.                 *  l     Print a line feed character (but no carriage return).
  1433.                 *  f     Print a form feed character.
  1434.                 *  \     Print the backslash character.
  1435.                 *  %     Print the percent sign character.
  1436.                 *  0xhh  Print ASCII code hh, represented by two hex digits.
  1437.  
  1438.                 C users should note a couple of differences between stdlib's
  1439.                 escape sequences and C's.  First, use "\%" to print a percent
  1440.                 sign within a format string, not "%%".  C doesn't allow the
  1441.                 use of "\%" because the C compiler processes "\%" at compile
  1442.                 time (leaving a single "%" in the object code) whereas printf
  1443.                 processes the format string at run-time.  It would see a single
  1444.                 "%" and treat it as a format lead-in character.  Stdlib's
  1445.                 printf, on the other hand, processes both the "\" and "%" and
  1446.                 run-time, therefore it can distinguish "\%".
  1447.  
  1448.                 Strings of the form "\0xhh" must contain exactly two hex
  1449.                 digits.  The current printf routine isn't robust enough to
  1450.                 handle sequences of the form "\0xh" which contain only a
  1451.                 single hex digit.  Keep this in mind if you find printf
  1452.                 chopping off characters after you print a value.
  1453.  
  1454.                 There is absolutely no reason to use any escape character
  1455.                 sequences except "\0x00".  Printf grabs all characters
  1456.                 following the call to printf up to the terminating zero byte
  1457.                 (which is why you'd need to use "\0x00" if you want to print
  1458.                 the null character, printf will not print such values).
  1459.                 Stdlib's printf routine doesn't care how those characters got
  1460.                 there.  In particular, you are not limited to using a single
  1461.                 string after the printf call.  The following is perfectly
  1462.         legal:
  1463.  
  1464.  
  1465.                 printf
  1466.                 db      "This is a string",13,10
  1467.                 db      "This is on a new line",13,10
  1468.                 db      "Print a backspace at the end of this line:"
  1469.                 db      8,13,10,0
  1470.  
  1471.  
  1472.                 Your code will run a tiny amount faster if you avoid the use
  1473.                 of the escape character sequences.  More importantly, the
  1474.                 escape character sequences take at least two bytes.  You can
  1475.                 encode most of them as a single byte by simply embedding the
  1476.                 ASCII code for that byte directly into the code stream.
  1477.                 Don't forget, you cannot embed a zero byte into the code
  1478.                 stream.  A zero byte terminates the format string.  Instead,
  1479.                 use the "\0x00" escape sequence.
  1480.  
  1481.                 Format sequences always between with "%".  For each format
  1482.                 sequence you must provide a far pointer to the associated
  1483.                 data immediately following the format string, e.g.,
  1484.  
  1485.                     printf
  1486.                     db      "%i %i",0
  1487.                     dd      i,j
  1488.  
  1489.                 Format sequences take the general form "%s\cn^f" where:
  1490.  
  1491.                 *       "%" is always the "%" character.  Use "\%" if you
  1492.                         actually want to print a percent sign.
  1493.                 *       s is either nothing or a minus sign ("-").
  1494.                 *       "\c" is also optional, it may or may not appear in
  1495.                         the format item.  "c" represents any printable
  1496.                         character.
  1497.                 *       "n" represents a string of 1 or more decimal digits.
  1498.                 *       "^" is just the caret (up-arrow) character.
  1499.                 *       "f" represents one of the format characters: i, d, x,
  1500.                         h, u, c, s, ld, li, lx, or lu.
  1501.  
  1502.                 The "s", "\c", "n", and "^" items are optional, the "%" and
  1503.                 "f" items must be present.  Furthermore, the order of these
  1504.                 items in the format item is very important.  The "\c" entry,
  1505.                 for example, cannot precede the "s" entry.  Likewise, the "^"
  1506.                 character, if present, must follow everything except the "f"
  1507.                 character(s).
  1508.  
  1509.                 The format characters i, d, x, h, u, c, s, ld, li, lx, and
  1510.                 lu control the output format for the data.  The i and d
  1511.                 format characters perform identical functions, they tell
  1512.                 printf to print the following value as a 16-bit signed
  1513.                 decimal integer.  The x and h format characters instruct
  1514.                 printf to print the specified value as a 16-bit or 8-bit
  1515.                 hexadecimal value (respectively).  If you specify u, printf
  1516.                 prints the value as a 16-bit unsigned decimal integer.
  1517.                 Using c tells printf to print the value as a single character.
  1518.                 S tells printf that you're supplying the address of a
  1519.                 zero-terminated character string, printf prints that string.
  1520.                 The ld, li, lx, and lu entries are long (32-bit) versions of
  1521.                 d/i, x, and u.  The corresponding address points at a 32-bit
  1522.                 value which printf will format and print to the standard output.
  1523.                 The following example demonstrates these format items:
  1524.  
  1525.                 printf
  1526.                 db      "I= %i, U= %u, HexC= %h, HexI= %x, C= %c, "
  1527.                 db      "S= %s",13,10
  1528.                 db      "L= %ld",13,10,0
  1529.                 dd      i,u,c,i,c,s,l
  1530.  
  1531.                 The number of far addresses (specified by operands to the "dd"
  1532.                 pseudo-opcode) must match the number of "%" format items in
  1533.                 the format string.  Printf counts the number of "%" format
  1534.                 items in the format string and skips over this many far
  1535.                 addresses following the format string.  If the number of
  1536.                 items do not match, the return address for printf will be
  1537.                 incorrect and the program will probably hang or otherwise
  1538.                 malfunction.  Likewise (as for the print routine), the format
  1539.                 string must end with a zero byte.  The addresses of the items
  1540.                 following the format string must point directly at the memory
  1541.                 locations where the specified data lies.
  1542.  
  1543.                 When used in the format above, printf always prints the
  1544.                 values using the minimum number of print positions for each
  1545.                 operand.  If you want to specify a minimum field width, you
  1546.                 can do so using the "n" format option.  A format item of the
  1547.                 format "%10d" prints a decimal integer using at least ten
  1548.                 print positions.  Likewise, "%16s" prints a string using at
  1549.                 least 16 print positions.  If the value to print requires
  1550.                 more than the specified number of print positions, printf
  1551.                 will use however many are necessary.  If the value to print
  1552.                 requires fewer, printf will always print the specified number,
  1553.                 padding the value with blanks.  Printf will print the value
  1554.                 right justified in the print field (regardless of the data's
  1555.                 type).  If you want to print the value left justified in the
  1556.                 output file, use the "-" format character as a prefix to the
  1557.                 field width, e.g.,
  1558.  
  1559.                 printf
  1560.                 db      "%-17s",0
  1561.                 dd      string
  1562.  
  1563.                 In this example, printf prints the string using a 17 character
  1564.                 long field with the string left justified in the output field.
  1565.                 By default, printf blank fills the output field if the value
  1566.                 to print requires fewer print positions than specified by the
  1567.                 format item.  The "\c" format item allows you to change the
  1568.                 padding character.  For example, to print a value, right
  1569.                 justified, using "*" as the padding character you would use
  1570.                 the format item "%\*10d".  To print it left justified you
  1571.                 would use the format item "%-\*10d".  Note that the "-" must
  1572.                 precede the "\*".  This is a limitation of the current
  1573.                 version of the software.  The operands must appear in this
  1574.                 order.  Normally, the address(es) following the printf
  1575.                 format string must be far pointers to the actual data to print.
  1576.                 On occasion, especially when allocating storage on the heap
  1577.                 (using malloc), you may not know (at assembly time) the
  1578.                 address of the object you want to print.  You may have only
  1579.                 a pointer to the data you want to print.  The "^" format
  1580.                 option tells printf that the far pointer following the format
  1581.                 string is the address of a pointer to the data rather than
  1582.                 the address of the data itself.  This option lets you access
  1583.                 the data indirectly.
  1584.  
  1585.                 Note: unlike C, stdlib's printf routine does not support
  1586.                 floating point output.  Putting floating point into printf
  1587.         would increase the size of this routine a tremendous amount.
  1588.         Since most people don't need the floating point output
  1589.         facilities, it doesn't appear here.  Check out PRINTFF.
  1590.  
  1591. Include:        stdlib.a or stdout.a
  1592.  
  1593.  
  1594.  
  1595. Routine:  PRINTFF
  1596. -----------------
  1597.  
  1598.  
  1599. Category:             Character Output Routine
  1600.  
  1601. Registers on Entry:   CS:RET- Points at format string and other parameters.
  1602.  
  1603. Registers on Return:  If your program prints floating point values, this
  1604.               routine modifies the floating point accumulator and
  1605.               floating point operand "pseudo-registers" in the
  1606.               floating point package.
  1607.  
  1608. Flags Affected:       None
  1609.  
  1610. Examples of Usage:
  1611.             printff
  1612.             db    "I = %d, R = %7.2f  F = 12.5e  G = 9.2gf\n",0
  1613.             dd    i, r, f, g
  1614.  
  1615. Description:  
  1616.         This code works just like printf except it also allows the
  1617.         output of floating point values.  The output formats are 
  1618.         the following:
  1619.  
  1620.         Single Precision:
  1621.  
  1622.          mm.nnF-    Prints a field width of mm chars with nn digits
  1623.                 appearing after the decimal point.
  1624.  
  1625.          nnE-        Prints a floating point value using scientific
  1626.                 notation in a field width of nn chars.
  1627.  
  1628.         Double Precision:
  1629.  
  1630.          mm.nnGF-    As above, for double precision values.
  1631.          nnGE-        As above, for double precision values.
  1632.  
  1633.         Extended Precision-
  1634.  
  1635.          mm.nnLF-    As above, for extended precision values.
  1636.          nnLE-        As above, for extended precision values.
  1637.  
  1638.  
  1639.         Since PRINTFF supports everything PRINTF does, you should not
  1640.         use both routines in the same program (just use PRINTF).  The
  1641.         PRINTF & PRINTFF macros check for this and will print a warning
  1642.         message if you've included both routines.  Using both will not
  1643.         cause your program to fail, but it will make your program
  1644.         unnecessarily larger.  You should not use PRINTFF unless you
  1645.         really need to print floating point values.  When you use
  1646.         PRINTFF, it forces the linker to load in the entire floating
  1647.         point package, making your program considerably larger.
  1648.  
  1649. Include:                  stdlib.a or fp.a
  1650.  
  1651.  
  1652.  
  1653. Conversion Routines
  1654. -------------------
  1655.  
  1656.  
  1657. The stdlib conversion routines follow a uniform format of storing the data
  1658. to be converted and returned.  Most routines accept input and return data
  1659. of either an ASCII string of characters, stored in the ES:DI register, or
  1660. integers, stored in the DX:AX register.  If a value is just a 16 or 8-bit
  1661. value then it will be stored in AX or AL.
  1662.  
  1663. Since there is a possibility of an error in the input values to be converted,
  1664. such as it does not contain a proper value to convert, we use the
  1665. carry flag to show error status.  If the error flag is set then an error has
  1666. occured and things are okay if the carry flag is clear.
  1667.  
  1668.  
  1669.  
  1670.  
  1671.  
  1672. Routine:  ATOL (2)
  1673. ------------------
  1674.  
  1675.  
  1676. Category:             Conversion Routine
  1677.  
  1678. Registers on Entry:   ES:DI- Points at string to convert
  1679.  
  1680. Registers on Return:  DX:AX- Long integer converted from string
  1681.               ES:DI- Points at first non-digit (ATOL2 only)
  1682.  
  1683. Flags Affected:       Carry flag- Error status
  1684.  
  1685. Examples of Usage:
  1686.               gets         ;Get a string from user
  1687.               ATOL         ;Convert to a value in DX:AX
  1688.  
  1689.  
  1690. Description:  ATOL converts the string of digits that ES:DI points at to a
  1691.           long (signed) integer value and returns this value in DX:AX.
  1692.           Note that the routine stops on the first non-digit.
  1693.           If the string does not begin with a digit, this routine returns
  1694.           zero.  The only exception to the "string of digits" only rule is
  1695.           that the number can have a preceding minus sign to denote a
  1696.           negative number.  Note that this routine does not allow leading
  1697.           spaces.  ATOL2 works in a similar fashion except it doesn't
  1698.           preserve the DI register.  That is, ATOL2 leaves DI pointing at
  1699.           the first character beyond the string of digits.  ATOL/ATOL2 both
  1700.           return the carry flag clear if it  translated the string of
  1701.           digits without error.  It returns the carry flag set if overflow
  1702.           occurred.
  1703.  
  1704.  
  1705. Include:                  stdlib.a or conv.a
  1706.  
  1707.  
  1708.  
  1709. Routine:  AtoUL (2)
  1710. -------------------
  1711.  
  1712. Category:            Conversion Routine
  1713.  
  1714. Register on entry:   ES:DI- address of the string to be converted
  1715.  
  1716. Register on return:  DX:AX- 32-bit unsigned integer
  1717.              ES:DI- Points at first character beyond digits (ATOUL2
  1718.                 only)
  1719.  
  1720. Flags affected:      Carry flag- Set if error, clear if okay.
  1721.  
  1722. Examples of Usage:
  1723.              les InputString
  1724.              AtoUL
  1725.  
  1726.  
  1727. Description:  AtoUL converts the string pointed by ES:DI to a 32-bit unsigned
  1728.           integer.  It places the 32-bit unsigned integer into the memory
  1729.           address pointed by DX:AX. If there is an error in conversion,
  1730.           the carry flag will set to one. If there is not an error, the
  1731.           carry flag will be set to zero.
  1732.  
  1733.           ATOUL2 does not preserve DI.  It returns with DI pointing at
  1734.           the first non-digit character in the string.
  1735.  
  1736. Include:        stdlib.a or conv.a
  1737.  
  1738.  
  1739.  
  1740. Routine:    ATOU (2)
  1741. --------------------
  1742.  
  1743. Category:            Conversion Routine
  1744.  
  1745. Register on entry:   ES:DI points at string to convert
  1746.  
  1747. Register on return:  AX-    unsigned 16-bit integer
  1748.              ES:DI- points at first non-digit (ATOU2 only)
  1749.  
  1750. Flags affected:      carry flag - error status
  1751.  
  1752. Example of Usage:
  1753.  
  1754. Description:    ATOU converts an ASCII string of digits, pointed to by ES:DI,
  1755.         to unsigned integer format. It places the unsigned 16-bit
  1756.         integer, converted from the string, into the AX register.
  1757.         ATOI works the same, except it handle unsigned 16-bit integers
  1758.         in the range 0..65535.
  1759.  
  1760.         ATOU2 leaves DI pointing at the first non-digit in the string.
  1761.  
  1762. Include:        stdlib.a or conv.a
  1763.  
  1764.  
  1765.  
  1766. Routine: ATOH (2)
  1767. -----------------
  1768.  
  1769. Category:             Conversion Routine
  1770.  
  1771. Registers on Entry:   ES:DI- Points to string to convert
  1772.  
  1773. Registers on Return:  AX- Unsigned 16-bit integer converted from hex string
  1774.               DI (ATOH2)- First character beyond string of hex digits
  1775.  
  1776. Flags Affected:       Carry = Error status
  1777.  
  1778. Example of Usage:
  1779.               les  DI, Str2Convrt
  1780.               atoh                  ;Convert to value in AX.
  1781.               putw                  ;Print word in AX.
  1782.  
  1783.  
  1784. Description:  ATOH converts a string of hexadecimal digits, pointed to by
  1785.           ES:DI, into unsigned 16-bit numeric form. It returns the value in
  1786.           the AX register.  If there is an error in conversion, the carry
  1787.           flag will set to one.  If there is not an error, the carry flag
  1788.           will be clear.  ATOH2 works the same except it leaves DI
  1789.           pointing at the first character beyond the string of hex digits.
  1790.  
  1791. Include:        stdlib.a or conv.a
  1792.  
  1793.  
  1794. Routine: ATOLH (2)
  1795. ------------------
  1796.  
  1797. Category:             Conversion Routine
  1798.  
  1799. Registers on Entry:   ES:DI- Points to string to convert
  1800.  
  1801. Registers on Return:  DX:AX- Unsigned 32-bit integer converted from hex string
  1802.               DI (ATOLH2)- First character beyond string of hex digits
  1803.  
  1804. Flags Affected:       Carry = Error status
  1805.  
  1806. Example of Usage:
  1807.               les  DI, Str2Convrt
  1808.               atolh                 ;Convert to value in DX:AX
  1809.  
  1810. Description:  ATOLH converts a string of hexadecimal digits, pointed to by
  1811.           ES:DI, into unsigned 32-bit numeric form. It returns the value in
  1812.           the DX:AX register.  If there is an error in conversion, the carry
  1813.           flag will set to one.  If there is not an error, the carry flag
  1814.           will be clear.  ATOLH2 works the same except it leaves the DI
  1815.           register pointing at the first non-hex digit.
  1816.  
  1817.  
  1818. Include:        stdlib.a or conv.a
  1819.  
  1820.  
  1821.  
  1822. Routine:   ATOI (2)
  1823. -------------------
  1824.  
  1825. Category:             Conversion Routine
  1826.  
  1827. Register on entry:    ES:DI- Points at string to convert.
  1828.  
  1829. Register on return:   AX- Integer converted from string.
  1830.               DI (ATOI2)- First character beyond string of digits.
  1831.  
  1832. Flags affected:       Error status
  1833.  
  1834. Examples of Usage:
  1835.               les  DI, Str2Convrt
  1836.               atoi                 ;Convert to value in AX
  1837.  
  1838.  
  1839. Description:   Works just like ATOL except it translates the string to a
  1840.            signed 16-bit integer rather than a 32-bit long integer.
  1841.  
  1842.  
  1843. Include:              stdlib.a or conv.a
  1844.  
  1845.  
  1846. Routine ITOA (2,M)
  1847. ------------------
  1848.  
  1849. Category:             Conversion Routine
  1850.  
  1851. Registers on Entry:   AX- Signed 16-bit value to convert to a string
  1852.               ES:DI- Pointer to buffer to hold result (ITOA/ITOA2
  1853.                  only).
  1854.  
  1855. Registers on Return:  ES:DI- Pointer to string containing converted
  1856.               characters (ITOA/ITOAM only).
  1857.               ES:DI- Pointer to zero-terminating byte of converted
  1858.                  string (ITOA2 only).
  1859.  
  1860. Flags Affected:       Carry flag is set on memory allocation error (ITOAM only)
  1861.  
  1862. Examples of Usage:
  1863.               mov     ax, -1234
  1864.               ITOAM                   ;Convert to string.
  1865.               puts                    ;Print it.
  1866.               free                    ;Deallocate string.
  1867.  
  1868.               mov     di, seg buffer
  1869.               mov     es, di
  1870.               lea     di, buffer
  1871.               mov     ax, -1234
  1872.               ITOA              ;Leaves string in BUFFER.
  1873.  
  1874.               mov     di, seg buffer
  1875.               mov     es, di
  1876.               lea     di, buffer
  1877.               mov     ax, -1234
  1878.               ITOA2              ;Leaves string in BUFFER and
  1879.                           ;ES:DI pointing at end of string.
  1880.  
  1881.  
  1882. Description:    These routines convert an integer value to a string of
  1883.         characters which represent that integer.  AX contains the
  1884.         signed integer you wish to convert.
  1885.  
  1886.         ITOAM automatically allocates storage on the heap for the
  1887.         resulting string, you do not have to pre-allocate this
  1888.         storage.  ITOAM returns a pointer to the (zero-terminated)
  1889.         string in the ES:DI registers.  It ignores the values in
  1890.         ES:DI on input.
  1891.  
  1892.         ITOA requires that the caller allocate the storage for the
  1893.         string (maximum you will need is seven bytes) and pass a
  1894.         pointer to this buffer in ES:DI.  ITOA returns with ES:DI
  1895.         pointing at the beginning of the converted string.
  1896.  
  1897.         ITOA2 also requires that you pass in the address of a buffer
  1898.         in the ES:DI register pair.  However, it returns with ES:DI
  1899.         pointing at the zero-terminating byte of the string.  This
  1900.         lets you easily build up longer strings via multiple calls
  1901.         to routines like ITOA2.
  1902.  
  1903. Include:        stdlib.a or conv.a
  1904.  
  1905.  
  1906.  
  1907. Routine:   UTOA (2,M)
  1908. ---------------------
  1909.  
  1910. Category:            Conversion Routine
  1911.  
  1912. Registers on entry:   AX - unsigned 16-bit integer to convert to a string
  1913.               ES:DI- Pointer to buffer to hold result (UTOA/UTOA2
  1914.                  only).
  1915.  
  1916. Registers on Return:  ES:DI- Pointer to string containing converted
  1917.               characters (UTOA/UTOAM only).
  1918.               ES:DI- Pointer to zero-terminating byte of converted
  1919.                  string (UTOA2 only).
  1920.  
  1921. Flags affected:       Carry set denotes malloc error (UTOAM only)
  1922.  
  1923. Example of Usage:
  1924.               mov     ax, 65000
  1925.               utoa
  1926.               puts
  1927.               free
  1928.  
  1929.               mov     di, seg buffer
  1930.               mov     es, di
  1931.               lea     di, buffer
  1932.               mov     ax, -1234
  1933.               ITOA              ;Leaves string in BUFFER.
  1934.  
  1935.               mov     di, seg buffer
  1936.               mov     es, di
  1937.               lea     di, buffer
  1938.               mov     ax, -1234
  1939.               ITOA2              ;Leaves string in BUFFER and
  1940.                           ;ES:DI pointing at end of string.
  1941.  
  1942.  
  1943. Description:    UTOAx converts a 16-bit unsigned integer value in AX to a
  1944.         string of characters which represents that value.  UTOA,
  1945.         UTOA2, and UTOAM behave in a manner analogous to ITOAx.  See
  1946.         the description of those routines for more details.
  1947.  
  1948.  
  1949. Include:       stdlib.a or conv.a
  1950.  
  1951.  
  1952.  
  1953. Routine:   HTOA (2,M)
  1954. ---------------------
  1955.  
  1956. Category:            Conversion Routine
  1957.  
  1958. Registers on entry:   AL - 8-bit integer to convert to a string
  1959.               ES:DI- Pointer to buffer to hold result (HTOA/HTOA2
  1960.                  only).
  1961.  
  1962. Registers on Return:  ES:DI- Pointer to string containing converted
  1963.               characters (HTOA/HTOAM only).
  1964.               ES:DI- Pointer to zero-terminating byte of converted
  1965.                  string (HTOA2 only).
  1966.  
  1967. Flags affected:      Carry set denotes memory allocation error (HTOAM only)
  1968.  
  1969.  
  1970. Description:    The HTOAx routines convert an 8-bit value in AL to the two-
  1971.         character hexadecimal representation of that byte.  Other
  1972.         that that, they behave just like ITOAx/UTOAx.  Note that
  1973.         the resulting buffer must have at least three bytes for
  1974.         HTOA/HTOA2.
  1975.  
  1976.  
  1977. Include:        stdlib.a or conv.a
  1978.  
  1979.  
  1980. Routine:  WTOA (2,M)
  1981. --------------------
  1982.  
  1983. Category:             Conversion Routine
  1984.  
  1985. Registers on Entry:   AX- 16-bit value to convert to a string
  1986.               ES:DI- Pointer to buffer to hold result (WTOA/WTOA2
  1987.                  only).
  1988.  
  1989. Registers on Return:  ES:DI- Pointer to string containing converted
  1990.               characters (WTOA/WTOAM only).
  1991.               ES:DI- Pointer to zero-terminating byte of converted
  1992.                  string (WTOA2 only).
  1993.  
  1994. Flags Affected:       Carry set denotes memory allocation error (WTOAM only)
  1995.  
  1996. Example of Usage:
  1997.               Like WTOA above
  1998.  
  1999.  
  2000. Description:  WTOAx converts the 16-bit value in AX to a string of four
  2001.           hexadecimal digits. It behaves exactly like HTOAx except
  2002.           it outputs four characters (and requires a five byte buffer).
  2003.  
  2004.  
  2005. Include:        stdlib.a or conv.a
  2006.  
  2007.  
  2008.  
  2009. Routine:  LTOA (2,M)
  2010. --------------------
  2011.  
  2012. Category:             Conversion Routine
  2013.  
  2014. Registers on entry:   DX:AX (contains a signed 32 bit integer)
  2015.               ES:DI- Pointer to buffer to hold result (LTOA/LTOA2
  2016.                  only).
  2017.  
  2018. Registers on Return:  ES:DI- Pointer to string containing converted
  2019.               characters (LTOA/LTOAM only).
  2020.               ES:DI- Pointer to zero-terminating byte of converted
  2021.                  string (LTOA2 only).
  2022.  
  2023. Flags affected:       Carry set if memory allocation error (LTOAM only)
  2024.  
  2025.  
  2026. Example of Usage: 
  2027.             mov    di, seg buffer    ;Get address of storage
  2028.             mov    es, di        ; buffer.
  2029.             lea    di, buffer
  2030.             mov    ax, word ptr value
  2031.             mov    dx, word ptr value+2
  2032.             ltoa
  2033.  
  2034. Description:    LtoA converts the 32-bit signed integer in DX:AX to a string
  2035.         of characters.  LTOA stores the string at the address specified
  2036.         in ES:DI (there must be at least twelve bytes available at
  2037.         this address) and returns with ES:DI pointing at this buffer.
  2038.         LTOA2 works the same way, except it returns with ES:DI
  2039.         pointing at the zero terminating byte.  LTOAM allocates
  2040.         storage for the string on the heap and returns a pointer
  2041.         to the string in ES:DI.
  2042.  
  2043. Include:        stdlib.a or conv.a
  2044.  
  2045.  
  2046.  
  2047. Routine:  ULTOA (2,M)
  2048. ---------------------
  2049.  
  2050. Category:             Conversion Routine
  2051.  
  2052. Registers on Entry:   DX:AX- Unsigned 32-bit value to convert to a string
  2053.               ES:DI- Pointer to buffer to hold result (LTOA/LTOA2
  2054.                  only).
  2055. Registers on Return:  ES:DI- Pointer to string containing converted
  2056.               characters (LTOA/LTOAM only).
  2057.               ES:DI- Pointer to zero-terminating byte of converted
  2058.                  string (LTOA2 only).
  2059.  
  2060. Flags Affected:       Carry is set if malloc error (ULTOAM only)
  2061.  
  2062. Example of Usage:  
  2063.                       Like LTOA
  2064.  
  2065.  
  2066. Description:  Like LTOA except this routine handles unsigned integer values.
  2067.  
  2068. Include:    stdlib.a or conv.a
  2069.  
  2070.  
  2071.  
  2072. Routine:  SPrintf (2,M)
  2073. -----------------------
  2074.  
  2075. Category:            Conversion Routine
  2076.              In-Memory Formatting Routine
  2077.  
  2078. Registers on entry:  CS:RET - Pointer to format string and operands of the
  2079.                   sprintf routine
  2080.              ES:DI-   Address of buffer to hold output string
  2081.                   (sprintf/sprintf2 only)
  2082.  
  2083. Register on return:  ES:DI register - pointer to a string containing
  2084.                       output data (sprintf/sprintfm only).
  2085.                       Pointer to zero-terminating byte at the
  2086.                       end of the converted string (sprintf2
  2087.                       only).
  2088.  
  2089. Flags affected:      Carry is set if memory allocation error (sprintfm only).
  2090.  
  2091. Example of Usage:
  2092.              sprintfm
  2093.              db      "I=%i, U=%u, S=%s",13,10,0
  2094.              db      i,u,s
  2095.              puts
  2096.              free
  2097.  
  2098.  
  2099. Description:   SPrintf is an in-memory formatting routine. It is similar to
  2100.            C's sprintf routine.
  2101.  
  2102.            The programmer selects the maximum length of the output string.
  2103.            SPrintf works in a manner quite similar to printf, except sprintf
  2104.            writes its output to a string variable rather than to the stdlib
  2105.            standard output.
  2106.  
  2107.            SPrintfm, by default, allocates 2048 characters for the string
  2108.            and then deallocates any unnecessary storage.  An external
  2109.            variable, sp_MaxBuf, holds the number of bytes to allocate upon
  2110.            entry into sprintfm.  If you wish to allocate more or less than
  2111.            2048 bytes when calling sprintf, simply change the value of this
  2112.            public variable (type is word).  Sprintfm calls malloc to
  2113.            allocate the storage dynamically.  You should call free to
  2114.            return this buffer to the heap when you are through with it.
  2115.  
  2116.            Sprintf and Sprintf2 expect you to pass the address of a buffer
  2117.            to them.  You are responsible for supplying a sufficiently
  2118.            sized buffer to hold the result.
  2119.  
  2120. Include:             stdlib.a or conv.a
  2121.  
  2122.  
  2123.  
  2124. Routine:  SScanf
  2125. ----------------
  2126.  
  2127. Category:              Conversion Routine
  2128.                Formatted In-Memory Conversion Routine
  2129.  
  2130. Registers on Entry:    ES:DI - points at string containing values to convert
  2131.  
  2132. Registers on return:   None
  2133.  
  2134. Flags affected:           None
  2135.  
  2136. Example of Usage:
  2137.  
  2138.           ; this code reads the values for i, j, and s from the characters
  2139.           ; starting at memory location Buffer.
  2140.  
  2141.                les   di, Buffer
  2142.                SScanf
  2143.                db    "%i %i %s",0
  2144.                dd     i, j, s
  2145.  
  2146.  
  2147. Description:  SScanf provides formatted input in a fashion analogous to scanf.
  2148.               The difference is that scanf reads in a line of text from the
  2149.               stdlib standard input whereas you pass the address of a sequence
  2150.               of characters to SScanf in es:di.
  2151.  
  2152.  
  2153. Include:                stdlib.a or conv.a
  2154.  
  2155.  
  2156.  
  2157.  
  2158. Routine:  ToLower
  2159. -----------------
  2160.  
  2161. Category:            Conversion Routine
  2162.  
  2163. Register on entry:   AL- Character to (possibly) convert
  2164.                 to lower case.
  2165.  
  2166. Register on return:  AL- Converted character.
  2167.  
  2168. Flags affected:      None
  2169.  
  2170. Example of usage:
  2171.              mov     al, char
  2172.              ToLower
  2173.  
  2174.  
  2175. Description:  ToLower checks the character in the AL register, if it is upper
  2176.           case it converts it to lower case.  If it is anything else,
  2177.           ToLower leaves the value in AL unchanged.  For high performance
  2178.           this routine is implemented as a macro rather than as a
  2179.           procedure call.  This routine is so short you would spend more
  2180.           time actually calling the routine than executing the code inside.
  2181.           However, the code is definitely longer than a (far) procedure
  2182.           call, so if space is critical and you're invoking this code
  2183.           several times, you may want to convert it to a procedure call to
  2184.           save a little space.
  2185.  
  2186.  
  2187. Include:             stdlib.a or conv.a
  2188.  
  2189.  
  2190.  
  2191. Routine:   ToUpper
  2192. ------------------
  2193.  
  2194. Category:             Conversion Routine
  2195.  
  2196. Registers on Entry:   AL- Character to (possibly) convert to upper case
  2197.  
  2198. Registers on Return:  AL- Converted character
  2199.  
  2200. Flags Affected:       None
  2201.  
  2202. Example of Usage:
  2203.               mov  al, char
  2204.               ToUpper
  2205.  
  2206.  
  2207. Description:  ToUpper checks the character in the AL register, if it is lower
  2208.           case it converts it to upper case.  If it is anything else,
  2209.           ToUpper leaves the value in AL unchanged.  For high performance
  2210.           this routine is implemented as a macro rather than as a
  2211.           procedure call (see ToLower, above).
  2212.  
  2213.  
  2214. Include:              stdlib.a or conv.a
  2215.  
  2216.  
  2217.  
  2218.  
  2219.  
  2220. Utility Routines
  2221. ----------------
  2222.  
  2223. The following routines are all Utility Routines.  The first routines listed
  2224. below compute the number of print positions required by a 16-bit and 32-bit
  2225. signed and unsigned integer value.  UlSize is like the LSize except it treats
  2226. the value in DX:AX as an unsigned long integer.  The next set of routines in
  2227. this section check the character in the AL register to see whether it is a
  2228. hexidecimal digit, if it alphabetic, if it is a lower case alphabetic, if it
  2229. is a upper case alphabetic, and if it is numeric.  Then there are some
  2230. miscellaneous routines (macros) which process command line parameters, invoke
  2231. DOS and exit the program.
  2232.  
  2233.  
  2234.  
  2235. Routine:  ISize
  2236. ---------------
  2237.  
  2238. Category:            Utility Routine
  2239.  
  2240. Register on entry:   AX- 16-bit value to compute the
  2241.                 output size for.
  2242.  
  2243. Register on return:  AX- Number of print positions
  2244.                 required by this number (including
  2245.                 the minus sign, if necessary).
  2246.  
  2247. Flags affected:      None
  2248.  
  2249. Example of usage:
  2250.              mov     ax, I
  2251.              ISize
  2252.              puti                    ;Prints positions
  2253.                          ;req'd by I.
  2254.  
  2255.  
  2256. Description:         This routine computes the number of print positions
  2257.              required by a 16-bit signed integer value.  ISize computes
  2258.              the minimum number of character positions it takes to print
  2259.              the signed decimal value in the AX register.  If the number
  2260.              is negative, it will include space for the minus sign in
  2261.              the count.
  2262.  
  2263.  
  2264. Include:             stdlib.a or util.a
  2265.  
  2266.  
  2267.  
  2268.  
  2269. Routine:  USize
  2270. ---------------
  2271.  
  2272. Category:            Utility Routine
  2273.  
  2274. Register on entry:   AX- 16 bit value to compute the
  2275.                 output size for
  2276.  
  2277. Register on return:  AX- number of print positions
  2278.              required by this number (including
  2279.              the minus sign, if necessary)
  2280.  
  2281. Flags affected:      None
  2282.  
  2283. Example of usage:
  2284.              mov     ax, I
  2285.              USize
  2286.              puti                    ;prints position
  2287.                          ;required by I
  2288.  
  2289.  
  2290. Description:         This routine computes the number of print positions
  2291.              required by a 16-bit signed integer value.  It also
  2292.              computes the number of print positions required by a
  2293.              16-bit unsigned value.  USize computes the minimum number
  2294.              of character positions it will take to print an unsigned
  2295.              decimal value in the AX register.  If the number is
  2296.              negative, it will include space for the minus sign in the
  2297.              count.
  2298.  
  2299.  
  2300. Include:             stdlib.a or util.a
  2301.  
  2302.  
  2303. Routine:  LSize
  2304. ---------------
  2305.  
  2306. Category:            Utility Routine
  2307.  
  2308. Register on entry:   DX:AX   - 32-bit value to compute the
  2309.                    output size for.
  2310.  
  2311. Register on return:  AX - Number of print positions
  2312.               required by this number (including
  2313.               the minus sign, if necessary).
  2314.  
  2315. Flags affected:      None
  2316.  
  2317. Example of Usage:
  2318.              mov     ax, word ptr L
  2319.              mov     dx, word ptr L+2
  2320.              LSize
  2321.              puti                    ;Prints positions
  2322.                          ;req'd by L.
  2323.  
  2324.  
  2325. Description:         This routine computes the number of print positions
  2326.              required by a 32-bit signed integer value.  LSize computes
  2327.              the minimum number of character positions it will take to
  2328.              print the signed decimal value in the DX:AX registers.  If
  2329.              the number is negative, it will include space for the minus
  2330.              sign in the count.
  2331.  
  2332.  
  2333. Include:             stdlib.a or util.a
  2334.  
  2335.  
  2336.  
  2337. Routine:  ULSize
  2338. ----------------
  2339.  
  2340. Category:             Utility Routine
  2341.  
  2342. Registers on Entry:   DX:AX - 32-bit value to compute the output size for.
  2343.  
  2344. Registers on return:  AX - number of print positions required by this number
  2345.  
  2346. Flags affected:       None
  2347.  
  2348. Example of Usage:
  2349.               mov     ax, word ptr L
  2350.               mov     dx, word ptr L+2
  2351.               ULSize
  2352.               puti                    ; Prints positions req'd by L
  2353.  
  2354.  
  2355. Description:          ULSize computes the minimum number of character
  2356.               positions it will take to print an unsigned decimal
  2357.               value in the DX:AX registers.
  2358.  
  2359.  
  2360. Include:              stdlib.a or util.a
  2361.  
  2362.  
  2363.  
  2364. Routine:  IsAlNum
  2365. -----------------
  2366.  
  2367. Category:             Utility routine
  2368.  
  2369. Register on entry:    AL - character to check.
  2370.  
  2371. Register on return:   None
  2372.  
  2373. Flags affected:       Zero flag - set if character is alphanumeric,
  2374.               clear if not.
  2375.  
  2376.  
  2377. Example of usage :    mov al, char
  2378.               IsAlNum
  2379.               je IsAlNumChar
  2380.  
  2381.  
  2382. Description :         This routine checks the character in the AL register to
  2383.               see if it is in the range A-Z, a-z, or 0-9.  Upon return,
  2384.               you can use the JE instruction to check to see if the
  2385.               character was in this range (or, conversely, you can use
  2386.               JNE to see if it is not in range).
  2387.  
  2388.  
  2389. Include:              stdlib.a or util.a
  2390.  
  2391.  
  2392. Routine:  IsXDigit
  2393. ------------------
  2394.  
  2395. Category:               Utility Routine
  2396.  
  2397. Register on Entry:     AL- character to check
  2398.  
  2399. Registers on Return:    None
  2400.  
  2401. Flags Affected:         Zero flag-  Set if character is a hex digit, clear if not
  2402.  
  2403.  
  2404. Example of Usage:       mov    al, char
  2405.             IsXDigit
  2406.             je     IsXDigitChar
  2407.  
  2408.  
  2409. Description:            This routine checks the character in the AL register to
  2410.             see if it is in the range A-F, a-f, or 0-9.  Upon
  2411.             return, you can use the JE instruction to check to see
  2412.             if the character was in this range (or, conversely,
  2413.             you can use jne to see if it is not in the range).
  2414.  
  2415.  
  2416. Include:                stdlib.a or util.a
  2417.  
  2418.  
  2419. Routine:   IsDigit
  2420. ------------------
  2421.  
  2422. Category:            Utility Routine
  2423.  
  2424. Register on entry:   AL- Character to check
  2425.  
  2426. Register on return:  None
  2427.  
  2428. Flags affected:         Zero flag- set if character is numeric, clear if not.
  2429.  
  2430. Example of Usage:    mov   al, char
  2431.              IsDigit
  2432.              je  IsDecChar
  2433.  
  2434.  
  2435. Description:         This routine checks the character in the AL register to
  2436.              see if it is in the range 0-9.  Upon return, you can use
  2437.              the JE instruction to check to see if the character was
  2438.              in the range (or, conversely, you can use JNE to see if it
  2439.              is not in the range).
  2440.  
  2441.  
  2442. Include:             stdlib.a or util.a
  2443.  
  2444.  
  2445. Routine:   IsAlpha
  2446. ------------------
  2447.  
  2448. Category:            Utility Routine
  2449.  
  2450. Register on entry:   AL- Character to check
  2451.  
  2452. Register on return:  None
  2453.  
  2454. Flags affected:         Zero flag- set if character is alphabetic, clear if not.
  2455.  
  2456. Example of Usage:    mov   al, char
  2457.              IsAlpha
  2458.              je   IsAlChar
  2459.  
  2460.  
  2461. Description:         This routine checks the character in the AL register to
  2462.              see if it is in the range A-Z or a-z.  Upon return, you
  2463.              can use the JE instruction to check to see if the character
  2464.              was in the range (or, conversely, you can use JNE to see
  2465.              if it is not in the range).
  2466.  
  2467. Include:             stdlib.a or util.a
  2468.  
  2469.  
  2470.  
  2471.  
  2472. Routine: IsLower
  2473. ----------------
  2474.  
  2475. Category:             Utility Routine
  2476.  
  2477. Registers on Entry:   AL- character to test
  2478.  
  2479. Registers on Return:  None
  2480.  
  2481.  
  2482. Flags Affected:       Zero = 1 if character is a lower case alphabetic character
  2483.               Zero = 0 if character is not a lower case alphabetic
  2484.               character
  2485.  
  2486. Example of Usage:     mov  AL, char        ; put char in AL
  2487.               IsLower              ; is char lower a-z?
  2488.               je  IsLowerChar      ; if yes, jump to IsLowerChar
  2489.  
  2490.  
  2491. Description:          This routine checks the character in the AL register to
  2492.               see if it is in the range a-z.  Upon return, you can use
  2493.               the JE instruction to check and see if the character was
  2494.               in this range (or you can use JNE to check and see if
  2495.               the character was not in this range).  This procedure is
  2496.               implemented as a macro for high performance.
  2497.  
  2498.  
  2499. Include:              stdlib.a or util.a
  2500.  
  2501.  
  2502. Routine:  IsUpper
  2503. -----------------
  2504.  
  2505. Category:             Utility Routine
  2506.  
  2507. Registers on Entry:   AL- character to check
  2508.  
  2509. Registers on Return:  None
  2510.  
  2511. Flags Affected:       Zero flag - set if character is uppercase alpha, clear
  2512.                   if not.
  2513.  
  2514.  
  2515. Example of Usage:     mov al, char
  2516.               IsUpper
  2517.               je IsUpperChar
  2518.  
  2519.  
  2520. Description:          This routine checks the character in the AL register to
  2521.               see if it is in the ranger A-Z.  Upon return, you can use
  2522.               the JE instruction to check to see if it not in the
  2523.               range).  It uses macro implementation for high performance.
  2524.  
  2525.  
  2526. Include:              stdlib.a or util.a
  2527.  
  2528.  
  2529. Routine:  Argc
  2530. --------------
  2531.  
  2532. Category:             Utility Routine
  2533.  
  2534. Registers on Entry:   None
  2535.  
  2536. Registers on Return:  CX-    Number of command line parameters
  2537.  
  2538. Flags Affected:       None
  2539.  
  2540.  
  2541. Example of Usage:     
  2542.             print
  2543.             db    "There were ",0
  2544.             argc
  2545.             mov    ax, cx
  2546.             puti
  2547.             print
  2548.             db    " command line parameters here",cr,lf,0
  2549.  
  2550. Description:    This routine returns the number of command line para-
  2551.         meters on the DOS command line.  Note that strings enclosed
  2552.         in quotation marks or apostrophes are counted as a single
  2553.         command line parameter.
  2554.  
  2555.  
  2556. Include:              stdlib.a or misc.a
  2557.  
  2558.  
  2559. Routine:  Argv
  2560. --------------
  2561.  
  2562. Category:             Utility Routine
  2563.  
  2564. Registers on Entry:   AX-    Which parameter to grab (1..n).
  2565.               PSP-    Global variable containing the DOS program
  2566.                 segment prefix value.
  2567.  
  2568. Registers on Return:  ES:DI-    Pointer to string on heap containing the
  2569.                 specified parameter (empty string if the
  2570.                 parameter does not exist).
  2571.  
  2572. Flags Affected:       carry-    Set if malloc error.
  2573.  
  2574.  
  2575. Example of Usage:     
  2576.             mov    ax, 2
  2577.             argv
  2578.             print
  2579.             db    "The second command line parameter is ",0
  2580.             puts
  2581.             free
  2582.  
  2583. Description:    
  2584.  This routine returns a string containing the specified command line argument.
  2585. You must pass the position number of the argument in AX; this routine returns
  2586. the specified string on the heap with ES:DI pointing at the string.  Note that
  2587. the command line parameters are numbered starting from one.  If you specify an
  2588. out of range value, this routine returns a pointer to a zero byte (the empty
  2589. string).
  2590.  
  2591.  
  2592. Include:              stdlib.a or misc.a
  2593.  
  2594.  
  2595. Routine:  GetEnv
  2596. ----------------
  2597.  
  2598. Category:             Utility Routine
  2599.  
  2600. Registers on Entry:   ES:DI-    Points at a string containing the name of
  2601.                 the environment variable you want to find.
  2602.               PSP-    Global variable containing the DOS program
  2603.                 segment prefix value.
  2604.  
  2605. Registers on Return:  ES:DI-    Pointer to string in the environment space
  2606.                 containing the characters immediately after
  2607.                 the name of the environment variable in the
  2608.                 environment string space.
  2609.  
  2610. Flags Affected:       carry-    Set if malloc error.
  2611.  
  2612.  
  2613. Example of Usage:     
  2614.             les    di, EnvVarStrPtr
  2615.             getenv
  2616.             print
  2617.             db    "The value of the environment variable is ",0
  2618.             puts
  2619.             free
  2620.  
  2621. Description:    
  2622.  
  2623.   This routine returns a pointer to the first characters following an
  2624. environment variable in the program's environment variable space.  It points
  2625. at the very first character following the name, so it typically points at
  2626. an equal sign (e.g., the PATH environment variable is typically of the form
  2627. "PATH=xxxxxxxx" and the "=" is the first char past the name).  If this routine
  2628. does not find the specified environment variable, it returns a pointer to
  2629. a single zero byte.  Since the pointer is in the environment space, you should
  2630. not store anything at this address.  Instead, first copy the string with STRDUP
  2631. if you need to modify it.
  2632.  
  2633. Include:              stdlib.a or misc.a
  2634.  
  2635.  
  2636. Routine:  DOS
  2637. -------------
  2638.  
  2639. Category:             Utility Routine
  2640.  
  2641. Registers on Entry:   AH-    DOS opcode
  2642.  
  2643. Registers on Return:  Depends on particular DOS call
  2644.  
  2645. Flags Affected:       Depends on DOS call.
  2646.  
  2647.  
  2648. Example of Usage:     
  2649.             mov    ah, 9
  2650.             DOS
  2651.              .
  2652.              .
  2653.              .
  2654.             DOS    7
  2655. Description:    
  2656.  
  2657.   This macro invokes DOS via the INT 21h interrupt.  If there is no parameter
  2658. to the macro, it simply issues the INT 21h instruction.  If a parameter is
  2659. present, it emits "mov ah, operand" followed by the INT 21h instruction.
  2660.  
  2661. Include:              stdlib.a or consts.a
  2662.  
  2663.  
  2664. Routine:  ExitPgm
  2665. -----------------
  2666.  
  2667. Category:             Utility Routine
  2668.  
  2669. Registers on Entry:  None
  2670.  
  2671. Registers on Return:  Doesn't return
  2672.  
  2673. Flags Affected:       N/A
  2674.  
  2675.  
  2676. Example of Usage:     
  2677.             ExitPgm
  2678. Description:    
  2679.  
  2680.   This macro exits the program and returns to DOS.
  2681.  
  2682. Include:              stdlib.a or consts.a
  2683.  
  2684.  
  2685.  
  2686. String Handling Routines
  2687. ------------------------
  2688.  
  2689. Manipulating text is a major part of many computer applications. Typically,
  2690. strings are inputed and interpreted. This interpretation may involve some
  2691. chores such as extracting certain part of the text, copying it, or comparing
  2692. with other strings.
  2693.  
  2694. The string manipulation routines in C provides various functions. Therefore,
  2695. the stdlib has some C-like string handling functions (e.g. strcpy, strcmp).
  2696. In C a string is an array of characters; similarly, the string are terminated
  2697. by a "0" as a null character. In general, the input strings of these routines
  2698. are pointed by ES:DI. In some routines, the carry flag will be set to indicate
  2699. an error.
  2700.  
  2701. The following string routines take as many as four different forms: strxxx,
  2702. strxxxl, strxxxm, and strxxxlm.  These routines differ in how they store
  2703. the destination string into memory and where they obtain their source strings.
  2704.  
  2705. Routines of the form strxxx generally expect a single source string address
  2706. in ES:DI or a source and destination string in ES:DI & DX:SI.  If these
  2707. routines produce a string, they generally store the result into the buffer
  2708. pointed at by ES:DI upon entry.  They return with ES:DI pointing at the
  2709. first character of the destination string.
  2710.  
  2711. Routines of the form strxxxl have a "literal source string".  A literal
  2712. source string follows the call to the routine in the code stream.  E.g.,
  2713.  
  2714.             strcatl
  2715.             db    "Add this string to ES:DI",0
  2716.  
  2717. Routines of the form strxxxm automatically allocate storage for a source
  2718. string on the heap and return a pointer to this string in ES:DI.
  2719.  
  2720. Routines of the form strxxxlm have a literal source string in the code
  2721. stream and allocate storage for the destination string on the heap.
  2722.  
  2723.  
  2724.  
  2725. Routine:  Strcpy (l)
  2726. --------------------
  2727.  
  2728. Category:             String Handling Routine
  2729.  
  2730. Registers on Entry:   ES:DI - pointer to source string (Strcpy only)
  2731.               CS:RET - pointer to  source  string (Strcpy1 only)
  2732.               DX:SI - pointer to destination string
  2733.  
  2734.  
  2735. Registers on return:  ES:DI - points at the destination string
  2736.  
  2737.  
  2738. Flags affected:          None
  2739.  
  2740.  
  2741. Example of Usage:
  2742.               mov     dx, seg Dest
  2743.               mov     si, offset Dest
  2744.               mov     di, seg Source
  2745.               mov     es, di
  2746.               mov     si, offset Source
  2747.               Strcpy
  2748.  
  2749.               mov     dx, seg Dest
  2750.               mov     si, offset Dest
  2751.               Strcpyl
  2752.               db      "String to copy",0
  2753.  
  2754.  
  2755. Description:  Strcpy is used to copy a zero-terminated string from one
  2756.           location to another.  ES:DI points at the source string,
  2757.           DX:SI points at the destination address.  Strcpy copies all
  2758.           bytes, up to and including the zero byte, from the source
  2759.           address to the destination address.  The target buffer must
  2760.           be large enough to hold the string.  Strcpy performs no error
  2761.           checking on the size of the destination buffer.
  2762.  
  2763.           Strcpyl copies the  zero-terminated string immediately following
  2764.           the call instruction to the destination address specified by
  2765.           DX:SI.  Again, this routine expects you to ensure that the
  2766.           taraget buffer is large enough to hold the result.
  2767.  
  2768.           Note: There are no "Strcpym" or "Strcpylm" routines.  The
  2769.           reason is simple: "StrDup" and "StrDupl" provide these functions
  2770.           using names which are familiar to MSC and Borland C users.
  2771.  
  2772. Include:              stdlib.a or strings.a
  2773.  
  2774.  
  2775. Routine:  StrDup (l)
  2776. --------------------
  2777.  
  2778. Category:            String Handling Routine
  2779.  
  2780. Register on entry:   ES:dI - pointer to source string (StrDup
  2781.              only).  CS:RET - Pointer to source string
  2782.              (StrDupl only).
  2783.  
  2784. Register on return:  ES:DI - Points at the destination string
  2785.              allocated on heap.  Carry=0 if operation
  2786.              successful.  Carry=0 if insufficient
  2787.              memory for new string.
  2788.  
  2789. Flags affected:      Carry flag
  2790.  
  2791. Example of usage:
  2792.              StrDupl
  2793.              db "String for StrDupl",0
  2794.              jc  MallocError
  2795.              mov word ptr Dest1, di
  2796.              mov word ptr Dest1+2, es  ;create another
  2797.                            ;copy of this
  2798.                            ;string. Note
  2799.                            ;that es:di points
  2800.                            ;at Dest1 upon
  2801.                            ;entry to StrDup,
  2802.                            ;but it points at
  2803.                            ;the new string on
  2804.                            ;exit
  2805.              StrDup
  2806.              jc MallocError
  2807.              mov word ptr Dest2, di
  2808.              mov word ptr Dest2+2, es
  2809.  
  2810.  
  2811. Description:  StrDup and StrDupl duplicate strings.  You pass them
  2812.           a pointer to the string (in es:di for strdup, via
  2813.           the return address for strdupl) and they allocate
  2814.           sufficient storage on the heap for a copy of this
  2815.           string.  Then these two routines copy their source
  2816.           strings to the newly allocated storage and return
  2817.           a pointer to the new string in ES:DI.
  2818.  
  2819.  
  2820. Include:             stdlib.a or strings.a
  2821.  
  2822.  
  2823. Routine:  Strlen
  2824. ----------------
  2825.  
  2826. Category:            String Handling Routine
  2827.  
  2828. Registers on entry:  ES:DI - pointer to source string.
  2829.  
  2830. Register on return:  CX - length of specified string.
  2831.  
  2832. Flags Affected:      None
  2833.  
  2834. Examples of Usage:
  2835.              les   di, String
  2836.              strlen
  2837.              mov   sl, cx
  2838.              printf
  2839.              db   "Length of '%s' is %d\n",0
  2840.              dd   String, sl
  2841.  
  2842.  
  2843. Description:  Strlen computes the length of the string whose address
  2844.           appears in ES:DI.  It returns the number of characters
  2845.           up to, but not including, the zero terminating byte.
  2846.  
  2847. Include:             stdlib.a or strings.a
  2848.  
  2849.  
  2850. Routine:  Strcat (m,l,ml)
  2851. -------------------------
  2852.  
  2853. Category:             String Handling Routine
  2854.  
  2855. Registers on Entry:   ES:DI- Pointer to first string
  2856.               DX:SI- Pointer to second string (Strcat and Strcatm only)
  2857.  
  2858.  
  2859. Registers on Return:  ES:DI- Pointer to new string (Strcatm and Strcatml only)
  2860.  
  2861. Flags Affected:       Carry = 0 if no error
  2862.               Carry = 1 if insufficient memory (Strcatm and Strcatml
  2863.                             only)
  2864.  
  2865.  
  2866. Example of Usage:     les  DI, String1
  2867.               mov  DX, seg String2
  2868.               lea  SI, String2
  2869.               Strcat                   ; String1 <- String1 + String2
  2870.  
  2871.               les  DI, String1
  2872.               Strcatl                  ; String1 <- String1 +
  2873.               db  "Appended String",0  ;            "Appended String",0
  2874.  
  2875.  
  2876.               les  DI, String1
  2877.               mov  DX, seg String2
  2878.               lea  SI, String2
  2879.               Strcatm                  ; NewString <- String1 + String2
  2880.               puts
  2881.               free
  2882.  
  2883.               les  DI, String1
  2884.               Strcatml                 ; NewString <- String1 +
  2885.               db  "Appended String",0  ;         "Appended String",0
  2886.               puts
  2887.               free
  2888.  
  2889.  
  2890. Description:  These routines concatenate two strings together.  They differ
  2891.           mainly in the location of their source and destination operands.
  2892.  
  2893.           Strcat concatenates the string pointed at by DX:SI to the end of
  2894.           the string pointed at by ES:DI in memory.  Both strings must be
  2895.           zero-terminated.  The buffer pointed at by ES:DI must be large
  2896.           enough to hold the resulting string.  Strcat does NOT perform
  2897.           bounds checking on the data.
  2898.  
  2899.           ( continued on next page )
  2900.  
  2901.  
  2902.  
  2903.  
  2904.  
  2905.  
  2906.  
  2907. Routine:  Strcat (m,l,ml)   ( continued )
  2908. -----------------------------------------
  2909.  
  2910.  
  2911.           Strcatm computes the length of the two strings pointed at by ES:DI
  2912.           and DX:SI and attempts to allocate this much storage on the heap.
  2913.           If it is not successful, Strcatm returns with the Carry flag set,
  2914.           otherwise it copies the string pointed at by ES:DI to the heap,
  2915.           concatenates the string DX:SI points at to the end of this string
  2916.           on the heap, and returns with the Carry flag clear and ES:DI
  2917.           pointing at the new (concatenated) string on the heap.
  2918.  
  2919.           Strcatl and Strcatml work just like Strcat and Strcatm except you
  2920.           supply the second string as a literal constant immediately AFTER
  2921.           the call rather than pointing DX:SI at it (see examples above).
  2922.  
  2923.  
  2924. Include:             stdlib.a or strings.a
  2925.  
  2926.  
  2927. Routine:  Strchr
  2928. ----------------
  2929.  
  2930. Category:            String Handling Routine
  2931.  
  2932. Register on entry:   ES:DI- Pointer to string.
  2933.             AL- Character to search for.
  2934.  
  2935. Register on return:  CX- Position (starting at zero)
  2936.              where Strchr found the character.
  2937.  
  2938. Flags affected:      Carry=0 if Strchr found the character.
  2939.              Carry=1 if the character was not present
  2940.                  in the string.
  2941.  
  2942. Example of usage:
  2943.              les di, String
  2944.              mov al, Char2Find
  2945.              Strchr
  2946.              jc  NotPresent
  2947.              mov CharPosn, cx
  2948.  
  2949.  
  2950. Description:  Strchr locates the first occurrence of a character within a
  2951.           string.  It searches through the zero-terminated string pointed
  2952.           at by es:di for the character passed in AL. If it locates the
  2953.           character, it returns the position of that character to the CX
  2954.           register.  The first character in the string corresponds to the
  2955.           location zero.  If the character is not in the string, Strchr
  2956.           returns the carry flag set.  CX's value is undefined in that
  2957.           case.  If Strchr locates the character in the string, it
  2958.           returns with the carry clear.
  2959.  
  2960.  
  2961. Include:             stdlib.a or strings.a
  2962.  
  2963.  
  2964. Routine:  Strstr (l)
  2965. --------------------
  2966.  
  2967. Category:            String Handling Routine
  2968.  
  2969. Register on entry:   ES:DI - Pointer to string.
  2970.              DX:SI - Pointer to substring(strstr).
  2971.              CS:RET - Pointer to substring (strstrl).
  2972.  
  2973. Register on return:  CX - Position (starting at zero)
  2974.              where Strstr/Strstrl found the
  2975.              character.  Carry=0 if Strstr/
  2976.              Strstrl found the character.
  2977.              Carry=1 if the character was not
  2978.              present in the string.
  2979.  
  2980. Flags affected:      Carry flag
  2981.  
  2982. Example of usage :
  2983.              les di, MainString
  2984.              lea si, Substring
  2985.              mov dx, seg Substring
  2986.              Strstr
  2987.              jc NoMatch
  2988.              mov i, cx
  2989.              printf
  2990.              db "Found the substring '%s' at location %i\n",0
  2991.              dd Substring, i
  2992.  
  2993.  
  2994. Description:  Strstr searches for the position of a substring
  2995.           within another string.  ES:DI points at the
  2996.           string to search through, DX:SI points at the
  2997.           substring.  Strstr returns the index into ES:DI's
  2998.           string where DX:SI's string is found.  If the
  2999.           string is found, Strstr returns with the carry
  3000.           flag clear and CX contains the (zero based) index
  3001.           into the string.  If Strstr cannot locate the
  3002.           substring within the string ES:DI points at, it
  3003.           returns the carry flag set.  Strstrl works just
  3004.           like Strstr except it excepts the substring to
  3005.           search for immediately after the call instruction
  3006.           (rather than passing this address in DX:SI).
  3007.  
  3008.  
  3009. Include:              stdlib.a or strings.a
  3010.  
  3011.  
  3012. Routine:  Strcmp (l)
  3013. --------------------
  3014.  
  3015. Category:            String Handling Routine
  3016.  
  3017. Registers on entry:  ES:DI contains the address of the first string
  3018.              DX:SI contains the address of the second string (strcmp)
  3019.              CS:RET (contains the address of the substring (strcmpl)
  3020.  
  3021. Register on return:  CX (contains the position where the two strings differ)
  3022.  
  3023. Flags affected:      Carry flag and zero flag (string1 > string2 if C + Z = 0)
  3024.                      (string1 < string2 if C = 1)
  3025.  
  3026. Example of Usage:
  3027.              les     di, String1
  3028.              mov     dx, seg String2
  3029.              lea     si, String2
  3030.              strcmp
  3031.              ja        OverThere
  3032.  
  3033.              les     di, String1
  3034.              strcmpl
  3035.              db     "Hello",0
  3036.              jbe     elsewhere
  3037.  
  3038.  
  3039.  
  3040. Description:  Strcmp compares the first strings pointed by ES:DI with
  3041.           the second string pointed by DX:SI. The carry and zero flag
  3042.           will contain the corresponding result. So unsigned branch
  3043.           instructions such as JA or JB is recommended. If string1
  3044.           equals string2, strcmp will return with CX containing the
  3045.           offset of the zero byte in the two strings.
  3046.  
  3047.           Strcmpl compares the first string pointed by ES:DI with
  3048.           the substring pointed by CS:RET. The carry and zero flag
  3049.           will contain the corresponding result. So unsigned branch
  3050.           instructions such as JA or JB are recommended. If string1
  3051.           equals to the substring, strcmp will return with CX
  3052.           containing the offset of the zero byte in the two strings.
  3053.  
  3054. Include:             stdlib.a or strings.a
  3055.  
  3056.  
  3057. Routine:  Strupr (m)
  3058. --------------------
  3059.  
  3060. Category:            String Handling Routine
  3061.              Conversion Routine
  3062.  
  3063. Register on entry:   ES:DI (contains the pointer to input string)
  3064.  
  3065. Register on return:  ES:DI (contains the pointer to input string
  3066.                with characters converted to upper case)
  3067.                Note: struprm allocates storage for a new
  3068.                string on the heap and returns the pointer
  3069.                to this routine in ES:DI.
  3070.  
  3071. Flags affected:      Carry = 1 if memory allocation error (Struprm only).
  3072.  
  3073. Example of Usage:
  3074.              les     di, lwrstr1
  3075.              strupr
  3076.              puts
  3077.  
  3078.              mov        di, seg StrWLwr
  3079.              mov    es, di
  3080.              lea    di, StrWLwr
  3081.              struprm
  3082.              puts
  3083.              free
  3084.  
  3085.  
  3086. Description:  Strupr converts the input string pointed by ES:DI to
  3087.           upper case.  It will actually modify the string you pass
  3088.           to it.
  3089.  
  3090.           Struprm first makes a copy of the string on the heap and
  3091.           then converts the characters in this new string to upper
  3092.           case.  It returns a pointer to the new string in ES:DI.
  3093.  
  3094. Include:             stdlib.a or strings.a
  3095.  
  3096.  
  3097. Routine:  Strlwr (m)
  3098. --------------------
  3099.  
  3100. Category:            String Handling Routine
  3101.              Conversion Routine
  3102.  
  3103. Register on entry:   ES:DI (contains the pointer to input string)
  3104.  
  3105. Register on return:  ES:DI (contains the pointer to input string
  3106.                with characters converted to lower case).
  3107.  
  3108. Flags affected:      Carry = 1 if memory allocation error (strlwrm only)
  3109.  
  3110.  
  3111. Example of Usage:
  3112.              les di, uprstr1
  3113.              strlwr
  3114.              puts
  3115.  
  3116.              mov        di, seg StrWLwr
  3117.              mov    es, di
  3118.              lea    di, StrWLwr
  3119.              strlwrm
  3120.              puts
  3121.              free
  3122.  
  3123.  
  3124.  
  3125.  
  3126. Description:  Strlwr converts the input string pointed by ES:DI to
  3127.           lower case. It will actually modify the string you pass
  3128.           to it.
  3129.  
  3130.           Strlwrm first copies the characters onto the heap and then
  3131.           returns a pointer to this string after converting all the
  3132.           alphabetic characters to lower case.
  3133.  
  3134.  
  3135. Include:             stdlib.a or strings.a
  3136.  
  3137.  
  3138.  
  3139. Routine:  Strset (m)
  3140. --------------------
  3141.  
  3142. Category:            String Handling Routine
  3143.  
  3144. Register on entry:   ES:DI contains the pointer to input string (StrSet only)
  3145.              AL    contains the character to copy
  3146.              CX    contains number of characters to allocate for
  3147.                the string (Strsetm only)
  3148.  
  3149. Register on return:  ES:DI pointer to newly allocated string (Strsetm only)
  3150.  
  3151. Flags affected:      Carry set if memory allocation error (Strsetm only)
  3152.  
  3153. Example of Usage:
  3154.              les     di, string1
  3155.              mov    al, " "        ;Blank fill string.
  3156.              Strset
  3157.  
  3158.              mov     cx, 32
  3159.              mov    al, "*"        ;Create a new string w/32
  3160.              Strsetm            ; asterisks.
  3161.              puts
  3162.              free
  3163.  
  3164.  
  3165. Description:  Strset overwrites the data on input string pointed by
  3166.           ES:DI with the character on AL.
  3167.  
  3168.           Strsetm creates a new string on the heap with the number
  3169.           of characters specified in CX.  All characters in the string
  3170.           are initialized with the value in AL.
  3171.  
  3172. Include:             stdlib.a or strings.a
  3173.  
  3174.  
  3175. Routine:  Strspan (l)
  3176. ---------------------
  3177.  
  3178. Category:             String Handling Routine
  3179.  
  3180. Registers on Entry:   ES:DI - Pointer to string to scan
  3181.               DX:SI - Pointer to character set (Strspan only)
  3182.               CS:RET- Pointer to character set (Strspanl only)
  3183.  
  3184. Registers on Return:  CX- First position in scanned string which does not
  3185.               contain one of the characters in the character set
  3186.  
  3187. Flags Affected:       None
  3188.  
  3189. Example of Usage:
  3190.               les  DI, String
  3191.               mov  DX, seg CharSet
  3192.               lea  SI, CharSet
  3193.               Strspan           ; find first position in String with a
  3194.               mov i, CX         ;                  char not in CharSet
  3195.               printf
  3196.               db  "The first char which is not in CharSet "
  3197.               db  "occurs at position %d in String.\n",0
  3198.               dd  i
  3199.  
  3200.               les  DI, String
  3201.               Strspanl          ; find first position in String which
  3202.               db   "aeiou",0    ; is not a vowel
  3203.               mov  j, CX
  3204.               printf
  3205.               db  "The first char which is not a vowel "
  3206.               db  "occurs at position %d in String.\n",0
  3207.               dd  j
  3208.  
  3209.  
  3210. Description:  Strspan(l) scans a string, counting the number of characters which
  3211.           are present in a second string (which represents a character set).
  3212.           ES:DI points at a zero-terminated string of characters to scan.
  3213.           DX:SI (strspan) or CS:RET (strspanl) points at another zero-
  3214.           terminated string containing the set of characters to compare
  3215.           against.  The position of the first character in the string
  3216.           pointed to by ES:DI which is NOT in the character set is returned.
  3217.           If all the characters in the string are in the character set, the
  3218.           position of the zero-terminating byte will be returned.
  3219.  
  3220.           Although strspan and (especially) strspanl are very compact and
  3221.           convenient to use, they are not particularly efficient.  The
  3222.           character set routines provide a much faster alternative at the
  3223.           expense of a little more space.
  3224.  
  3225.  
  3226. Include:               stdlib.a or strings.a
  3227.  
  3228.  
  3229. Routine:  Strcspan, Strcspanl
  3230. -----------------------------
  3231.  
  3232. Category:             String Handling Routine
  3233.  
  3234. Registers on Entry:   ES:DI - Pointer to string to scan
  3235.               DX:SI - Pointer to character set (Strcspan only)
  3236.               CS:RET- Pointer to character set (Strcspanl only)
  3237.  
  3238. Registers on Return:  CX- First position in scanned string which contains one
  3239.               of the characters in the character set
  3240.  
  3241. Flags Affected:       None
  3242.  
  3243. Example of Usage:
  3244.               les  DI, String
  3245.               mov  DX, seg CharSet
  3246.               lea  SI, CharSet
  3247.               Strcspan          ; find first position in String with a
  3248.               mov i, CX         ;                      char in CharSet
  3249.               printf
  3250.               db  "The first char which is in CharSet "
  3251.               db  "occurs at position %d in String.\n",0
  3252.               dd  i
  3253.  
  3254.               les  DI, String
  3255.               Strcspanl         ; find first position in String which
  3256.               db   "aeiou",0    ; is a vowel.
  3257.               mov  j, CX
  3258.               printf
  3259.               db  "The first char which is a vowel occurs "
  3260.               db  "at position %d in String.\n",0
  3261.               dd  j
  3262.  
  3263.  
  3264. Description:  Strcspan(l) scans a string, counting the number of characters
  3265.           which are NOT present in a second string (which represents a
  3266.           character set).  ES:DI points at a zero-terminated string of
  3267.           characters to scan.  DX:SI (strcspan) or CS:RET (strcspanl) points
  3268.           at another zero-terminated string containing the set of characters
  3269.           to compare against.  The position of the first character in the
  3270.           string pointed to by ES:DI which is in the character set is
  3271.           returned.  If all the characters in the string are not in the
  3272.           character set, the position of the zero-terminating byte will be
  3273.           returned.
  3274.  
  3275.           Although strcspan and strcspanl are very compact and convenient to
  3276.           use, they are not particularly efficient.  The character set
  3277.           routines provide a much faster alternative at the expense of a
  3278.           little more space.
  3279.  
  3280. Include:              stdlib.a or strings.a
  3281.  
  3282.  
  3283. Routine:  StrIns (m,l,ml)
  3284. -------------------------
  3285.  
  3286. Category:             String Handling Routine
  3287.  
  3288. Registers on Entry:   ES:DI - Pointer to destination string (to insert into)
  3289.               DX:SI - Pointer to string to insert
  3290.                       (StrIns and StrInsm only)
  3291.               CX    - Insertion point in destination string
  3292.  
  3293. Registers on Return:  ES:DI - Pointer to new string (StrInsm and StrInsml only)
  3294.  
  3295. Flags Affected:       Carry = 0 if no error
  3296.               Carry = 1 if insufficient memory
  3297.                    (StrInsm and StrInsml only)
  3298.  
  3299.  
  3300. Example of Usage:
  3301.               les  DI, DestStr
  3302.               mov  DX, word ptr SrcStr+2
  3303.               mov  SI, word ptr SrcStr
  3304.               mov  CX, 5
  3305.               StrIns     ; Insert SrcStr before the 6th char of DestStr
  3306.  
  3307.               les  DI, DestStr
  3308.               mov  CX, 2
  3309.               StrInsl    ; Insert "Hello" before the 3rd char of DestStr
  3310.               db  "Hello",0
  3311.  
  3312.               les  DI, DestStr
  3313.               mov  DX, word ptr SrcStr+2
  3314.               mov  SI, word ptr SrcStr
  3315.               mov  CX, 11
  3316.               StrInsm      ; Create a new string by inserting SrcStr
  3317.                    ;         before the 12th char of DestStr
  3318.               puts
  3319.               putcr
  3320.               free
  3321.  
  3322.  
  3323. Description:  These routines insert one string into another string.  ES:DI
  3324.           points at the string into which you want to insert another.  CX
  3325.           contains the position (or index) where you want the string
  3326.           inserted.  This index is zero-based, so if CX contains zero, the
  3327.           source string will be inserted before the first character in the
  3328.           destination string.  If CX contains a value larger than the size
  3329.           of the destination string, the source string will be appended to
  3330.           the destination string.
  3331.  
  3332.           StrIns inserts the string pointed at by DX:SI into the string
  3333.           pointed at by ES:DI at position CX.  The buffer pointed at by
  3334.           ES:DI must be large enough to hold the resulting string.  StrIns
  3335.           does NOT perform bounds checking on the data.
  3336.  
  3337.      ( continued on next page )
  3338.  
  3339.  
  3340. Routine:  StrIns (m,l,ml)   ( continued )
  3341. -----------------------------------------
  3342.  
  3343.           StrInsm does not modify the source or destination strings, but
  3344.           instead attempts to allocate a new buffer on the heap to hold the
  3345.           resulting string.  If it is not successful, StrInsm returns with
  3346.           the Carry flag set, otherwise the resulting string is created and
  3347.           its address is returned in the ES:DI registers.
  3348.  
  3349.           StrInsl and StrInsml work just like StrIns and StrInsm except you
  3350.           supply the second string as a literal constant immediately AFTER
  3351.           the call rather than pointing DX:SI at it (see examples above).
  3352.  
  3353.  
  3354.  
  3355. Routine:  StrDel, StrDelm
  3356. -------------------------
  3357.  
  3358. Category:              String Handling Routine
  3359.  
  3360. Registers on Entry:    ES:DI -  pointer to string
  3361.                CX - deletion point in  string
  3362.                AX - number of characters to delete
  3363.  
  3364. Registers on return:   ES:DI - pointer to new string (StrDelm only)
  3365.  
  3366. Flags  affected:       Carry = 1 if memory allocation error,  0 if okay
  3367.                (StrDelm only).
  3368.  
  3369. Example of Usage:
  3370.                les     di,  Str2Del
  3371.                mov     cx,  3          ; Delete starting at 4th char
  3372.                mov     ax,  5          ; Delete five characters
  3373.                StrDel                  ; Delete in place
  3374.  
  3375.                les     di,  Str2Del2
  3376.                mov     cx,  5
  3377.                mov     ax,  12
  3378.                StrDelm
  3379.                puts
  3380.                free
  3381.  
  3382.  
  3383. Description:  StrDel deletes characters from a string.  It works by computing
  3384.           the beginning and end of the deletion point.  Then it copies all
  3385.           the characters from the end of the deletion point to the end of
  3386.           the string (including the zero byte) to the beginning of the
  3387.           deletion point.  This covers up (thereby effectively deleting)
  3388.           the undesired characters in the string.
  3389.  
  3390.           Here are two degenerate cases to worry about -- 1) when you
  3391.           specify a deletion point which is beyond the end of the string;
  3392.           and 2) when the deletion point is within the string but the
  3393.           length of the deletion takes you beyond the end of the string.
  3394.           In the first case StrDel simply ignores the deletion request.  It
  3395.           does not modify the original string.  In the second case,
  3396.           StrDel simply deletes everything from the deletion point to the
  3397.           end of the string.
  3398.  
  3399.           StrDelm works just like StrDel except it does not delete the
  3400.           characters in place.  Instead, it creates a new string on the
  3401.           heap consisting of the characters up to the deletion point and
  3402.           those following the characters to delete.  It returns a pointer
  3403.           to the new string on the heap in ES:DI, assuming that it
  3404.           properly allocated the storage on the heap.
  3405.  
  3406. Include:               stdlib.a or strings.a
  3407.  
  3408.  
  3409. Routine:  StrRev, StrRevm
  3410. -------------------------
  3411.  
  3412. Author:               Michael Blaszczak (.B  ekiM)
  3413.  
  3414. Category:             String Handling Routine
  3415.  
  3416. Registers on Entry:   ES:DI - pointer to string
  3417.  
  3418. Registers on return:  ES:DI - pointer to new string (StrRevm only).
  3419.  
  3420. Flags affected:       Carry  = 1 if memory allocation error, 0 if okay
  3421.               (StrRevm only).
  3422.  
  3423. Example of Usage:
  3424.  
  3425. Description:  StrRev reverses the characters in a string.  StrRev reverses,
  3426.           in place, the characters in the string that ES:SI points at.
  3427.           StrRevm creates a new string on the heap (which contains the
  3428.           characters in the string ES:DI points at, only reversed) and
  3429.           returns a pointer to the new string in ES:DI.  If StrRevm
  3430.           cannot allocate sufficient memory for the string, it returns
  3431.           with the carry flag set.
  3432.  
  3433.  
  3434. Include:              stdlib.a or strings.a
  3435.  
  3436.  
  3437. Routine:  ToHex
  3438. ---------------
  3439.  
  3440. Category:             String Handling Routine/ Conversion Routine
  3441.  
  3442. Registers on Entry:   ES:DI - pointer to byte array
  3443.               BX-     memory base address for bytes
  3444.               CX-     number of entries in byte array
  3445.  
  3446. Registers on return:  ES:DI - pointer to Intel Hex format string.
  3447.  
  3448. Flags affected:       Carry  = 1 if memory allocation error, 0 if okay
  3449.            
  3450.  
  3451. Example of Usage:
  3452.  
  3453.         mov    bx, 100h    ;Put data at address 100h in hex file.
  3454.         mov    cx, 10h        ;Total of 16 bytes in this array.
  3455.         les    di, Buffer    ;Pointer to data bytes
  3456.         ToHex            ;Convert to Intel HEX string format.
  3457.         puts            ;Print it.
  3458.  
  3459. Description:  
  3460.  
  3461. ToHex converts a stream of binary values to Intel Hex format.  Intel HEX format
  3462. is a common ASCII data interchange format for binary data.  It takes the
  3463. following form:
  3464.  
  3465.     : BB HHLL RR DDDD...DDDD SS <cr> <lf>
  3466.  
  3467. (Note:spaces were added for clarity, they are not actually present in the
  3468. hex string)
  3469.  
  3470. BB is a pair of hex digits which represent the number of data bytes (The DD
  3471. entries) and is the value passed in CX.
  3472.  
  3473. HHLL is the hexadecimal load address for these data bytes (passed in BX).
  3474.  
  3475. RR is the record type.  ToHex always produces data records with the RR field
  3476. containing "00".  If you need to output other field types (usually just an
  3477. end record) you must create that string yourself.  ToHex will not do it.
  3478.  
  3479. DD...DD is the actual data in hex form.  This is the number of bytes specified
  3480. in the BB field.
  3481.  
  3482. SS is the two's complement of the checksum (which is the sum of the binary
  3483. values of the BB, HH, LL, RR, and all DD fields).
  3484.  
  3485. This routine allocates storage for the string on the heap and returns a pointer
  3486. to that string in ES:DI.
  3487.  
  3488. Include:              stdlib.a or strings.a
  3489.  
  3490.  
  3491. Memory Management Routines
  3492. --------------------------
  3493.  
  3494. The stdlib memory management routines let you dynamically allocate storage on
  3495. the heap.  These routines are somewhat similar to those provided by the "C"
  3496. programming language.  However, these routines do not perform garbage
  3497. collection, as this would introduce too many restrictions and have a very
  3498. adverse effect on speed.
  3499.  
  3500. The following paragraph gives a description of how the memory management
  3501. routines work.  These routines may be updated in future revisions, however,
  3502. so you should never make assumptions about the structure of the memory
  3503. management record (described below) or else your code may not work on the
  3504. next revision.
  3505.  
  3506. The allocation/deallocation routines should be fairly fast.  Malloc and free
  3507. use a modified first/next fit algorithm which lets the system quickly find a
  3508. memory block of the desired size without undue fragmentation problems (average
  3509. case).  The memory manager data structure has an overhead of eight bytes
  3510. (meaning each malloc operation requires at least eight more bytes than you ask
  3511. for) and a granularity of 16 bytes.  The overhead (eight bytes) per allocated
  3512. block may seem rather high, but that is part of the price to pay for faster
  3513. malloc and free routines.  All pointers are far pointers and each new item is
  3514. allocated on a paragraph boundary.  The current memory manager routines always
  3515. allocate (n+8) bytes, rounding up to the next multiple of 16 if the result is
  3516. not evenly divisible by sixteen.  The first eight bytes of the structure are
  3517. used by the memory management routines, the remaining bytes are available for
  3518. use by the caller (malloc, et. al., return a pointer to the first byte beyond
  3519. the memory management overhead structure).
  3520.  
  3521.  
  3522.  
  3523.  
  3524. Routine:  MemInit
  3525. -----------------
  3526.  
  3527. Category:               Memory Management Routine
  3528.  
  3529. Registers on Entry:     DX - number of paragraphs to reserve
  3530.  
  3531. Globals Affected:       zzzzzzseg - segment name of the last segment in your
  3532.                     program
  3533.             PSP - public word variable which holds the PSP value
  3534.                   for your program
  3535.  
  3536. Registers on return:    CX - number of paragraphs actually reserved by MemInit
  3537.  
  3538. Flags affected:         Carry = 0 if no error.
  3539.             Carry = 1 if error; AX contains DOS error code.
  3540.  
  3541.  
  3542. Example of Usage:
  3543.                         ; Don't forget to set up PSP
  3544.                         ; and zzzzzzseg before calling
  3545.                         ; MemInit
  3546.             mov     dx, dx          ; Allocate all available RAM
  3547.             MemInit
  3548.             jc      MemoryError     ; CX contains the number of
  3549.                         ; paragraphs actually
  3550.                         ; allocated
  3551.  
  3552.  
  3553. Description:  This routine initializes the memory manager system.  You must
  3554.           call it before using any routines which call any of the memory
  3555.           manager procedures (since a good number of the stdlib routines
  3556.           call the memory manager, you should get in the habit of always
  3557.           calling this routine.)  The system will "die a horrible death"
  3558.           if you call a memory manager routine (like malloc) without first
  3559.           calling MemInit.
  3560.  
  3561.           This routine expects you to define (and set up) two global
  3562.           names: zzzzzzseg and PSP.  "zzzzzzseg" is a dummy segment which
  3563.           must be the name of the very last segment defined in your
  3564.           program.  MemInit uses the name of this segment to determine the
  3565.           address of the last byte in your program.  If you do not
  3566.           declare this segment last, the memory manager will overwrite
  3567.           anything which follows zzzzzzseg.  The "shell.asm" file
  3568.           provides you with a template for your programs which properly
  3569.           defines this segment.
  3570.  
  3571.           PSP should be a word variable which contains the program segment
  3572.           prefix value for your  program.  MS-DOS passes the PSP value to
  3573.           your program in the DS and ES registers.  You should save this
  3574.           value in the PSP variable.  Don't forget to make PSP a public
  3575.           symbol in your main program's source file.  The "shell.asm" file
  3576.           demonstrates how to properly set up this value.
  3577.  
  3578.           The DX register contnains the number of 16-byte paragraphs you
  3579.           want to reserve for the heap.  If DX contains zero, MemInit will
  3580.           allocate all of the available memory to the heap.  If your
  3581.           program is going to allow the user to run a copy of the command
  3582.           interpreter, or if your program is going to EXEC some other
  3583.           program, you should not allocate all storage to the heap.
  3584.           Instead, you should reserve  some memory for those programs.
  3585.           By setting DX to some value other than zero, you can tell MemInit
  3586.           how much memory you want to reserve for the heap.  All left over
  3587.           memory will be available for other system (or program) use.
  3588.           If the value in DX is larger than the amount of available RAM,
  3589.           MemInit will split the available memory in half and reserve half
  3590.           for the heap leaving the other half unallocated.  If you want to
  3591.           force this situation (to leave half available memory for other
  3592.           purposes), simply load DX with 0FFFFH before calling MemInit.
  3593.           There will never be this much memory available, so this will
  3594.           force MemInit to split the available RAM between the heap and
  3595.           unallocated storage.
  3596.  
  3597.           On return from MemInit, the CX register contains the number of
  3598.           paragraphs actually allocated.  You can use this value to see if
  3599.           MemInit has actually allocated the number of paragraphs you
  3600.           requested.  You  can also use this value to determine how much
  3601.           space is available when you elect to split the free space
  3602.           between the heap and the unallocated portions.
  3603.  
  3604.           If all goes well, this routine returns the carry flag clear.
  3605.           If a DOS memory manager error occurs, this routine returns the
  3606.           carry flag set and the DOS error code in the AX register.
  3607.  
  3608.  
  3609. Include:                stdlib.a or memory.a
  3610.  
  3611.  
  3612. Routine:  Malloc
  3613. ----------------
  3614.  
  3615. Category:              Memory Management Routine
  3616.  
  3617. Registers on Entry:    CX - number of bytes to reserve
  3618.  
  3619. Registers on return:   CX - number of bytes actually reserved by Malloc
  3620.                ES:DI - ptr to 1st byte of memory allocated by Malloc
  3621.  
  3622. Flags affected:        Carry=0 if no error.
  3623.                Carry=1 if insufficient memory.
  3624.  
  3625. Example of Usage:
  3626.                mov     cx, 256
  3627.                Malloc
  3628.                jnc     GoodMalloc
  3629.                print   db    "Insufficient memory to continue.",cr,lf,0
  3630.                jmp   Quit
  3631.       GoodMalloc:  mov   es:[di], 0          ;Init string to NULL
  3632.  
  3633.  
  3634. Description:  Malloc is the workhorse routine you use to allocate a block of
  3635.           memory.  You give it the number of bytes you need and if it
  3636.           finds a block large enough, it will  allocate the requested
  3637.           amount and return a pointer to that block.
  3638.  
  3639.           Most memory managers require  a small amount of overhead for each
  3640.           block they allocate.  Stdlib's (current) memory manager requires
  3641.           an overhead of eight bytes.  Furthermore, the grainularity is 16
  3642.           bytes.  This means that Malloc always allocates blocks of memory
  3643.           in paragraph multiples.  Therefore, Malloc may actually reserve
  3644.           more storage than you specify. Therefore, the value returned in
  3645.           CX may be somewhat greater than the requested value.  By setting
  3646.           the minimum allocation size to a paragraph, however, the
  3647.           overhead is reduced and the speed of Malloc is improved by a
  3648.           considerable amount.
  3649.  
  3650.           Stdlib's memory management does not do any garbage collection.
  3651.           Doing so would place too many demands on Malloc's users.
  3652.           Therefore, it is quite possible for you to fragment memory with
  3653.           multiple calls to maloc, realloc, and free.  You could wind up in
  3654.           a situation where there is enough free memory to satisfy your
  3655.           request, but there isn't a single contiguous block large enough
  3656.           for the request.  Malloc treats this as an insufficient memory
  3657.           error and returns with the carry flag set.
  3658.  
  3659.           If Malloc cannot allocate a block of the requested size, it
  3660.           returns with the carry flag set.  In this situation, the contents
  3661.           of ES:DI is undefined.  Attempting to dereference this pointer
  3662.           will produce erratic and, perhaps, disasterous results.
  3663.  
  3664. Include:              stdlib.a or memory.a
  3665.  
  3666.  
  3667. Routine:  Realloc
  3668. -----------------
  3669.  
  3670. Category:  Memory Management Routine
  3671.  
  3672. Registers on Entry:   CX - number of bytes to reserve
  3673.               ES:DI - pointer to block to  reallocate.
  3674.  
  3675. Registers on return:  CX - number of bytes actually reserved by Realloc.
  3676.               ES:DI - pointer to first byte of memory allocated by
  3677.                   Realloc.
  3678.  
  3679. Flags affected:       Carry = 0 if no error.
  3680.               Carry = 1 if insufficient memory.
  3681.  
  3682. Example of Usage:
  3683.             mov    cx, 1024    ;Change block size to 1K
  3684.             les    di, CurPtr    ;Get address of block into ES:DI
  3685.             realloc
  3686.             jc    BadRealloc
  3687.             mov    word ptr CurPtr, di
  3688.             mov    word ptr CurPtr+2, es
  3689.  
  3690.  
  3691. Description:  Realloc lets you change the size of an allocated block in the
  3692.           heap.  It allows you to make the block larger or smaller.
  3693.           If you make the  block smaller, Realloc simply frees (returns
  3694.           to the heap) any leftover bytes at the end of the block.  If
  3695.           you make the block larger, Realloc goes out and allocates a
  3696.           block of the requested size, copies the bytes form the old
  3697.           block to the beginning of the new block (leaving the bytes at
  3698.           the end of the new block uninitialized)), and then frees the
  3699.           old block.
  3700.  
  3701.  
  3702. Include:               stdlib.a or memory.a
  3703.  
  3704.  
  3705. Routine:  Free
  3706. --------------
  3707.  
  3708. Category:               Memory Management Routine
  3709.  
  3710. Registers on Entry:     ES:DI - pointer to block to deallocate
  3711.  
  3712. Registers on return:    None
  3713.  
  3714. Flags affected:         Carry = 0 if no error.
  3715.             Carry = 1 if ES:DI doesn't point at a Free block.
  3716.  
  3717. Example of Usage:
  3718.             les     di, HeapPtr
  3719.             Free
  3720.  
  3721. Description:  Free (possibly) deallocates storage allocated on the heap by
  3722.           malloc or Realloc.  Free returns this storage to heap so other
  3723.           code can reuse it later.  Note, however, that Free doesn't
  3724.           always return storage to the heap.  The memory manager data
  3725.           structure keeps track of the number of pointers currently
  3726.           pointing at a block on the heap (see DupPtr, below).  If you've
  3727.           set up several pointers such that they point at the same block,
  3728.           Free will not deallocate the storage until you've freed all of
  3729.           the pointers which point at the block.
  3730.  
  3731.           Free usually returns an error code (carry flag = 1) if you
  3732.           attempt to Free a block which is not currently allocated or if
  3733.           you pass it a memory address which was not returned by malloc
  3734.           (or Realloc).  By no means is this routine totally robust.
  3735.           If you start calling free with arbitrary pointers in es:di
  3736.           (which happen to be pointing into the heap) it is possible,
  3737.           under certain circumstances, to confuse Free and it will attempt
  3738.           to free a block it really should not.
  3739.  
  3740.           This problem could be solved by adding a large amount of extra
  3741.           code to the free routine, but it would slow it down considerably.
  3742.           Therefore, a little safety has been sacrificed for a lot of
  3743.           speed.  Just make sure your code is correct and everything will
  3744.           be fine!
  3745.  
  3746.  
  3747. Include:               stdlib.a or memory.a
  3748.  
  3749.  
  3750. Routine:  DupPtr
  3751. ----------------
  3752.  
  3753. Category:             Memory Manager Routine
  3754.  
  3755. Registers on Entry:   ES:DI - pointer to block
  3756.  
  3757. Registers on return:  None
  3758.  
  3759. Flags affected:       Carry = 0 if no error.
  3760.               Carry = 1 if es:di doesn't point at a free block.
  3761.  
  3762. Example of Usage:
  3763.               les     di,  Ptr
  3764.               DupPtr
  3765.  
  3766.  
  3767. Description:  DupPtr increments the pointer count for the block at the
  3768.           specifiied address.  Malloc sets this counter to one.  Free
  3769.           decrements it by one.  If free decrements the value and it
  3770.           becomes zero, free will release the storage to the heap for
  3771.           other use.  By using DupPtr you can tell the memory manager
  3772.           that you have several pointers pointing  at the same block
  3773.           and that it shouldn't deallocate the storage until you free
  3774.           all of those pointers.
  3775.  
  3776.  
  3777. Include:              stdlib.a or memory.a
  3778.  
  3779.  
  3780. Routine:  IsInHeap
  3781. ------------------
  3782.  
  3783. Category:             Memory Management Routine
  3784.  
  3785. Registers on Entry:   ES:DI - pointer to a block
  3786.  
  3787. Registers on return:  None
  3788.  
  3789. Flags affected:       Carry = 0 if ES:DI is a valid pointer.
  3790.               Carry = 1 if not.
  3791.  
  3792. Example of Usage:
  3793.             les    di, MemPtr
  3794.             IsInHeap
  3795.             jc    NotInHeap
  3796.  
  3797. Description:  This routine lets you know if es:di contains the address of
  3798.           a byte in the heap somewhere.  It does not tell you if es:di
  3799.           contains a valid pointer returned by malloc (see IsPtr, below).
  3800.           For example, if es:di contains the address of some particular
  3801.           element of an array (not necessarily the first element)
  3802.           allocated on the heap, IsInHeap will return with the carry clear
  3803.           denoting that the es:di points somewhere in the heap.  Keep in
  3804.           mind that calling this routine does not validate the pointer;
  3805.           it could be pointing at a byte which is part of the memory
  3806.           manager data structure rather than at actual data (since the
  3807.           memory manager maintains that informatnion within the
  3808.           bounds of the heap). This routine is mainly useful for seeing
  3809.           if something is allocated on the heap as opposed to somewhere
  3810.           else (like your code, data, or stack segment).
  3811.  
  3812.  
  3813. Include:              stdlib.a or memory.a
  3814.  
  3815.  
  3816. Routine:  IsPtr
  3817. ---------------
  3818.  
  3819. Category:               Memory Management Routine
  3820.  
  3821. Registers on Entry:     ES:DI - pointer to block
  3822.  
  3823. Registers on return:    None
  3824.  
  3825. Flags affected:         Carry = 0 if es:di is a valid pointer.
  3826.             Carry = 1 if not.
  3827.  
  3828. Example of Usage:
  3829.             les    di, MemPtr
  3830.             IsPtr
  3831.             jc    NotAPtr
  3832.  
  3833.  
  3834.  
  3835. Description:  IsPtr is much more specific than IsInHeap.  This routine returns
  3836.           the carry flag clear if and only if es:di contains the address
  3837.           of a properly allocated (and currently allocated) block on the
  3838.           heap.  This pointer must be a value returned by Malloc, Realloc,
  3839.           or DupPtr and that block must be currently allocated for IsPtr
  3840.           to return the carry flag clear.
  3841.  
  3842.  
  3843. Include:                stdlib.a or memory.a
  3844.  
  3845.  
  3846. Character Set Routines
  3847. ----------------------
  3848.  
  3849. The character set routines let you deal with groups of characters as a set
  3850. rather than a string.  A set is an unordered collection of objects where
  3851. membership (presence or absence) is the only important quality.  The stdlib
  3852. set routines were designed to let you quickly check if an ASCII character is
  3853. in a set, to quickly add characters to a set or remove characters from a set.
  3854. These operations are the ones most commonly used on character sets.  The
  3855. other operations (like union, intersection, difference, etc.) are useful, but
  3856. are not as popular as the former routines.  Therefore, the data structure
  3857. has been optimized for sets to handle the membership and add/delete operations
  3858. at the slight expense of the others.
  3859.  
  3860. Character sets are implemented via bit vectors.  A "1" bit means that an item
  3861. is present in the set and a "0" bit means that the item is absent from the
  3862. set.  The most common implementation of a character set is to use thirty-two 
  3863. consecutive bytes, eight bytes per, giving 256 bits (one bit for each char-
  3864. acter in the character set).  While this makes certain operations (like 
  3865. assignment, union, intersection, etc.) fast and convenient, other operations
  3866. (membership, add/remove items) run much slower.  Since these are the more 
  3867. important operations, a different data structure is used to represent sets.  
  3868. A faster approach is to simply use a byte value for each item in the set.  
  3869. This offers a major advantage over the thirty-two bit scheme:  for operations 
  3870. like membership it is very fast (since all you have got to do is index into 
  3871. an array and test the resulting value).  It has two drawbacks:  first, oper-
  3872. ations like set assignment, union, difference, etc., require 256 operations 
  3873. rather than thirty-two; second, it takes eight times as much memory.
  3874.  
  3875. The first drawback, speed, is of little consequence.  You will rarely use the
  3876. the operations so affected, so the fact that they run a little slower will be
  3877. of little consequence.  Wasting 224 bytes is a problem, however.  Especially
  3878. if you have a lot of character sets.
  3879.  
  3880. The approach used here is to allocate 272 bytes.  The first eight bytes con-
  3881. tain bit masks, 1, 2, 4, 8, 16, 32, 64, 128.  These masks tell you which bit
  3882. in the following 264 bytes is associated with the set.  This facilitates 
  3883. putting eight sets into 272 bytes (34 bytes per character set).  This provides
  3884. almost the speed of the 256-byte set with only a two byte overhead.  In the
  3885. stdlib.a file there is a macro that lets you define a group of character
  3886. sets:  set.  The macro is used as follows:
  3887.  
  3888.     set set1, set2, set3, ... , set8
  3889.  
  3890. You must supply between one and eight labels in the operand field.  These are
  3891. the names of the sets you want to create.  The set macro automatically 
  3892. attaches these labels to the appropriate mask bytes in the set.  The actual
  3893. bit patterns for the set begin eight bytes later (from each label).  There-
  3894. fore, the byte corresponding to chr(0) is staggered by one byte for each
  3895. set (which explains the other eight bytes needed above and beyond the 256 
  3896. required for the set).  When using the set manipulation routines, you should
  3897. always pass the address of the mask byte (i.e., the seg/offset of one of the 
  3898. labels above) to the particular set manipulation routine you are using. 
  3899. Passing the address of the structure created with the macro above will 
  3900. reference only the first set in the group.
  3901.  
  3902. Note that you can use the set operations for fast pattern matching appli-
  3903. cations.  The set membership operation for example, is much faster that the 
  3904. strspan routine found in the string package.  Proper use of character sets
  3905. can produce a program which runs much faster than some of the equivalent
  3906. string operations.
  3907.  
  3908.  
  3909. Routine:  Createsets
  3910. --------------------
  3911.  
  3912. Category:             Character Set Routine
  3913.  
  3914. Registers on Entry:   no parameters passed
  3915.  
  3916. Registers on return:  ES:DI - pointer to eight sets
  3917.  
  3918. Flags affected:       Carry = 0 if no error. Carry = 1 if insufficient
  3919.               memory to allocate storage for sets.
  3920.  
  3921. Example of Usage:
  3922.               Createsets
  3923.               jc      NoMemory
  3924.               mov     word ptr SetPtr,   di
  3925.               mov     word ptr SetPtr+2, es
  3926.  
  3927. Description:  Createsets allocates 272 bytes on the heap.   This is sufficient
  3928.           room for eight character sets.  It then initializes the first
  3929.           eight bytes of this storage with the proper mask values for
  3930.           each set.  Location es:0[di] gets set to 1, location es:1[di]
  3931.           gets 2, location es:2[di] gets 4, etc.  The Createsets routine
  3932.           also initializes all of the sets to the empty set by clearing
  3933.           all the bits to zero.
  3934.  
  3935. Include:              stdlib.a or charsets.a
  3936.  
  3937.  
  3938. Routine:  EmptySet
  3939. ------------------
  3940.  
  3941. Category:             Character Set Routine
  3942.  
  3943. Registers on Entry:   ES:DI - pointer to first byte of desired set
  3944.  
  3945. Registers on return:  None
  3946.  
  3947. Flags affected:          None
  3948.  
  3949. Example of Usage:
  3950.               les     di,  SetPtr
  3951.               add     di,  3          ; Point at 4th set in group.
  3952.               Emptyset
  3953.  
  3954.  
  3955. Description:  Emptyset clears out the bits in a character set to zero
  3956.           (thereby setting it to the empty set).  Upon entry, es:di must
  3957.           point at the first byte of the character set you want to clear.
  3958.           Note that this is not the address returned by Createsets.  The
  3959.           first eight bytes of a character set structure are the
  3960.           addresses of eight different sets.  ES:DI must point at one of
  3961.           these bytes upon entry into Emptyset.
  3962.  
  3963. Include:              stdlib.a or charsets.a
  3964.  
  3965.  
  3966. Routine:  Rangeset
  3967. ------------------
  3968.  
  3969. Category:             Character Set Routine
  3970.  
  3971. Registers on entry:   ES:DI (contains the address of the first byte of the set)
  3972.               AL    (contains the lower bound of the items)
  3973.               AH    (contains the upper bound of the items)
  3974.  
  3975. Registers on return:  None
  3976.  
  3977. Flags affected:       None
  3978.  
  3979. Example of Usage:
  3980.               lea di, SetPtr
  3981.               add di, 4
  3982.               mov al, 'A'
  3983.               mov ah, 'Z'
  3984.               rangeset
  3985.  
  3986.  
  3987. Description:  This routine adds a range of values to a set with ES:DI as the
  3988.           pointer to the set, AL as the lower bound of the set, and
  3989.           AH as the upper bound of the set (AH has to be greater than
  3990.           AL, otherwise, there will an error).
  3991.  
  3992. Include:              stdlib.a or charsets.a
  3993.  
  3994.  
  3995. Routine:  Addstr (l)
  3996. --------------------
  3997.  
  3998. Category:             Character Set Routine
  3999.  
  4000. Registers on Entry:   ES:DI- pointer to first byte of desired set
  4001.               DX:SI- pointer to string to add to set (Addstr only)
  4002.               CS:RET-pointer to string to add to set (Addstrl only)
  4003.  
  4004. Registers on Return:  None
  4005.  
  4006. Flags Affected:       None
  4007.  
  4008. Example of Usage:
  4009.               les     di, SetPtr
  4010.               add     di, 1           ;Point at 2nd set in group.
  4011.               mov     dx, seg CharStr ;Pointer to string
  4012.               lea     si, CharStr     ; chars to add to set.
  4013.               addstr                  ;Union in these characters.
  4014. ;
  4015.               les     di, SetPtr      ;Point at first set in group.
  4016.               addstrl
  4017.               db      "AaBbCcDdEeFf0123456789",0
  4018. ;
  4019.  
  4020.  
  4021. Description:  Addstr lets you add a group of characters to a set by
  4022.           specifying a string containing the characters you want in
  4023.           the set.  To Addstr you pass a pointer to a zero-terminated
  4024.           string in dx:si.  Addstr will add (union) each character
  4025.           from this string into the set.
  4026.  
  4027.           Addstrl works the same way except you pass the string as
  4028.           a literal string constant in the code stream rather than
  4029.           via ES:DI.
  4030.  
  4031. Include:              stdlib.a or charsets.a
  4032.  
  4033.  
  4034. Routine:  Rmvstr (l)
  4035. --------------------
  4036.  
  4037.  
  4038. Category:             Character Set Routine
  4039.  
  4040.  
  4041. Registers on entry:   ES:DI contains the address of first byte of a set
  4042.               DX:SI contains the address of string to be removed
  4043.                  from a set (Rmvstr only)
  4044.               CS:RET pointer to string to add to set (Rmvstrl only)
  4045.  
  4046.  
  4047. Registers on return:  None
  4048.  
  4049.  
  4050. Flags affected:       None
  4051.  
  4052.  
  4053. Example of Usage:
  4054.               les     di, SetPtr
  4055.               mov     dx, seg CharStr
  4056.               lea     si, CharStr
  4057.               rmvstr
  4058.  
  4059.               mov     dx, seg CharStr
  4060.               lea     si, CharStr
  4061.               rmvstrl
  4062.               db          "ABCDEFG",0
  4063.  
  4064.  
  4065. Description:  This routine is to remove a string from a set with ES:DI
  4066.           pointing to its first byte, and DX:SI pointing to the
  4067.           string to be removed from the set.
  4068.  
  4069.           For Rmvstrl, the string of characters to remove from the
  4070.           set follows the call in the code stream.
  4071.  
  4072. Include:              stdlib.a or charsets.a
  4073.  
  4074.  
  4075. Routine:  AddChar
  4076. -----------------
  4077.  
  4078. Category:             Character Set Routine
  4079.  
  4080. Registers on Entry:   ES:DI- pointer to first byte of desired set
  4081.               AL- character to add to the set
  4082.  
  4083. Registers on Return:  None
  4084.  
  4085. Flags affected:       None
  4086.  
  4087. Example of Usage:
  4088.               les     di, SetPtr
  4089.               add     di, 1           ;Point at 2nd set in group.
  4090.               mov     al, Ch2Add      ;Character to add to set.
  4091.               addchar
  4092.  
  4093.  
  4094. Description:  AddChar lets you add a single character (passed in AL)
  4095.           to a set.
  4096.  
  4097. Include:              stdlib.a or charsets.a
  4098.  
  4099.  
  4100. Routine:  Rmvchar
  4101. -----------------
  4102.  
  4103. Category:             Character Set Routine
  4104.  
  4105. Registers on entry:   ES:DI (contains the address of first byte of a set)
  4106.               AL    (contains the character to be removed)
  4107.  
  4108. Registers on return:  None
  4109.  
  4110. Flags affected:          None
  4111.  
  4112. Example of Usage:
  4113.               lea di, SetPtr
  4114.               add di, 7        ;Point at eighth set in group.
  4115.               mov al, Ch2Rmv
  4116.               Rmvchar
  4117.  
  4118. Description:  This routine removes the character in AL from a set.
  4119.           ES:SI points to the set's mask byte. The corresponding
  4120.           bit in the set is cleared to zero.
  4121.  
  4122. Include:              stdlib.a or charsets.a
  4123.  
  4124.  
  4125. Routine:  Member
  4126. ----------------
  4127.  
  4128. Category:             Character Set Routine
  4129.  
  4130. Registers on entry:   ES:DI (contains the address of first byte of a set)
  4131.               AL    (contains the character to be compared)
  4132.  
  4133. Registers on return:  None
  4134.  
  4135. Flags affected:       Zero flag (Zero = 1 if the character is in the set
  4136.                  Zero = 0 if the character is not in the set)
  4137.  
  4138. Example of Usage:
  4139.               les di, SetPtr
  4140.               add di, 1
  4141.               mov al, 'H'
  4142.               member
  4143.               je IsInSet
  4144.  
  4145.  
  4146. Description:  Member is used to find out if the character in AL is in a set
  4147.           with ES:DI pointing to its mask byte. If the character is in
  4148.           the set, the zero flag is set to 1. If not, the zero flag is
  4149.           set to zero.
  4150.  
  4151. Include:              stdlib.a or charsets.a
  4152.  
  4153.  
  4154. Routine:  CopySet
  4155. -----------------
  4156.  
  4157. Category:            Character Set Routine
  4158.  
  4159. Register on entry:   ES:DI- pointer to first byte of destination set.
  4160.              DX:SI- pointer to first byte of source set.
  4161.  
  4162. Register on Return:  None
  4163.  
  4164. Flags affected:      None
  4165.  
  4166. Example of Usage:
  4167.              les     di, SetPtr
  4168.              add     di, 7           ;Point at 8th set in group.
  4169.              mov     dx, seg SetPtr2 ;Point at first set in group.
  4170.              lea     si, SetPtr2
  4171.              copyset
  4172.  
  4173.  
  4174. Description:  CopySet copies the items from one set to another.  This is a
  4175.           straight assignment, not a union operation.  After the
  4176.           operation, the destination set is identical to the source set,
  4177.           both in terms of the element present in the set and absent
  4178.           from the set.
  4179.  
  4180.  
  4181. Include:             stdlib.a or charsets.a
  4182.  
  4183.  
  4184. Routine:  SetUnion
  4185. ------------------
  4186.  
  4187. Category:            Character Set Routine
  4188.  
  4189. Register on entry:   ES:DI - pointer to first byte of destination set.
  4190.              DX:SI - pointer to first byte of source set.
  4191.  
  4192. Register on return:  None
  4193.  
  4194. Flags affected:      None
  4195.  
  4196. Example of Usage:    les   di, SetPtr
  4197.              add   di, 7              ;point at 8th set in group.
  4198.              mov   dx, seg SetPtr2    ;point at 1st set in group.
  4199.              lea   si, sSetPtr2
  4200.              unionset
  4201.  
  4202.  
  4203. Description:  The SetUnion routine computes the union of two sets.
  4204.           That is, it adds all of the items present in a source set
  4205.           to a destination set.  This operation preserves items
  4206.           present in the destination set before the SetUnion
  4207.           operation.
  4208.  
  4209. Include:             stdlib.a or charsets.a
  4210.  
  4211.  
  4212. Routine:  SetIntersect
  4213. ----------------------
  4214.  
  4215. Category:            Character Set Routine
  4216.  
  4217. Register on entry:   ES:DI - pointer to first byte of destination set.
  4218.              DX:SI - pointer to first byte of source set.
  4219.  
  4220. Register on return:  None
  4221.  
  4222. Flags affected:      None
  4223.  
  4224. Example of Usage:
  4225.              les   di, SetPtr
  4226.              add   di, 7              ;point at 8th set in group.
  4227.              mov   dx, seg SetPtr2    ;point at 1st set in group.
  4228.              lea   si, SetPtr2
  4229.              setintersect
  4230.  
  4231. Description:  SetIntersect computes the intersection of two sets, leaving
  4232.           the result in the destination set.  The new set consists
  4233.           only of those items which previously appeared in
  4234.           both the source and destination sets.
  4235.  
  4236. Include:             stdlib.a or charsets.a
  4237.  
  4238.  
  4239. Routine:  SetDifference
  4240. -----------------------
  4241.  
  4242. Category:            Character Set Routine
  4243.  
  4244. Register on entry:   ES:DI - pointer to the first byte of destination set.
  4245.              DX:SI - pointer to the first byte of the source set.
  4246.  
  4247. Register on return:  None
  4248.  
  4249. Flags affected:      None
  4250.  
  4251. Example of Usage:
  4252.              les   di, SetPtr
  4253.              add   di, 7               ;point at 8th set in group.
  4254.              mov   dx, seg SetPtr2     ;point at 1st set in group.
  4255.              lea   si, SetPtr2
  4256.              setdifference
  4257.  
  4258.  
  4259. Description:  SetDifference computes the result of (ES:DI) := (ES:DI) -
  4260.           (DX:SI).  The destination set is left with its original
  4261.           items minus those items which are also in the source set.
  4262.  
  4263. Include:             stdlib.a or charsets.a
  4264.  
  4265.  
  4266. Routine:  Nextitem
  4267. ------------------
  4268.  
  4269. Category:             Character Set Routine
  4270.  
  4271. Registers on entry:   ES:DI (contains the address of first byte of the set)
  4272.  
  4273. Registers on return:  AL (contains the first item in the set)
  4274.  
  4275. Flags affected:       None
  4276.  
  4277. Example of Usage:
  4278.               les di, SetPtr
  4279.               add di, 7        ;Point at eighth set in group.
  4280.               nextitem
  4281.  
  4282.  
  4283. Description:  Nextitem is the routine to search the first character (item)
  4284.           in the set with ES:DI pointing to its mask byte. AL will
  4285.           return the character in the set. If the set is empty, AL
  4286.           will contain zero.
  4287.  
  4288. Include:              stdlib.a or charsets.a
  4289.  
  4290.  
  4291. Routine:  Rmvitem
  4292. -----------------
  4293.  
  4294. Category:             Character Set Routine
  4295.  
  4296. Registers on entry:   ES:DI (contains the address fo first byte of the set)
  4297.  
  4298. Registers on return:  AL (contains the first item in the set)
  4299.  
  4300. Flags affected:       None
  4301.  
  4302. Example of Usage:
  4303.               les di, SetPtr
  4304.               add di, 7
  4305.               rmvitem
  4306.  
  4307. Description:  Rmvitem locates the first available item in the set and
  4308.           removes it with ES:DI pointing to its mask byte. AL will
  4309.           return the item removed. If the set is empty, AL will
  4310.           return zero.
  4311.  
  4312. Include:              stdlib.a or charsets.a
  4313.  
  4314.  
  4315.  
  4316. Floating Point Routines
  4317. -----------------------
  4318.  
  4319. The floating point routines provide a basic floating point package for
  4320. 80x86 assembly language users.  The floating point package deals with
  4321. four different floating point formats: IEEE 32-bit, 64-bit, and 80-bit
  4322. formats, and an internal 81-bit format.  The external formats mostly
  4323. support the IEEE standard except for certain esoteric values such as
  4324. denormalized numbers, NaNs, infinities, and other such cases.
  4325.  
  4326. The package provides two "pseudo-registers", a floating point accumulator
  4327. and a floating point operand.  It provides routines to load and store these
  4328. pseudo-registers from memory operands (using the various formats) and then
  4329. all other operations apply to these two operands.  All computations use the
  4330. internal 81-bit floating point format.  The package automatically converts
  4331. between the internal format and the external format when loading and storing
  4332. values.
  4333.  
  4334. Do not write code which assumes the internal format is 81 bits.  This format
  4335. will change in the near future when I get a chance to add guard bits to
  4336. all the computations.  If your code assumes 81 bits, it will break at that
  4337. point.  Besides, there is no reason your code should count on the size of
  4338. the internal operations anyway.  Stick with the IEEE formats and you'll
  4339. be much better off (since your code can be easily upgraded to deal with
  4340. numeric coprocessors).
  4341.  
  4342. WARNING: These routines have not been sufficiently tested as of 10/10/91.
  4343. Use them with care.  Report any problems with these routines to Randy Hyde
  4344. via the electronic addresses provided in this document or by sending a
  4345. written report to UC Riverside.  As I get more time, I will further test
  4346. these routines and add additional functions to the package.
  4347.  
  4348.                     *** Randy Hyde
  4349.  
  4350.  
  4351.  
  4352. Routine:  lsfpa
  4353. ---------------
  4354.  
  4355. Category:             Floating point Routine
  4356.  
  4357. Registers on entry:   ES:DI points at a single precision (32-bit) value to load
  4358.  
  4359. Registers on return:  None
  4360.  
  4361. Flags affected:       None
  4362.  
  4363. Example of Usage:
  4364.             les di, FPValue
  4365.             lsfpa
  4366.  
  4367. Description:    LSFPA loads a single precision floating point value into the
  4368.         internal floating point accumulator.  It also converts the
  4369.         32-bit format to the internal 81-bit format used by the
  4370.         floating point package.
  4371.  
  4372. Include:    stdlib.a or fp.a
  4373.  
  4374. Routine:  ssfpa
  4375. ---------------
  4376.  
  4377. Category:             Floating point Routine
  4378.  
  4379. Registers on entry:   ES:DI points at a single precision (32-bit) value where
  4380.               this routine should store the floating point acc.
  4381.  
  4382. Registers on return:  None
  4383.  
  4384. Flags affected:       Carry set if conversion error.
  4385.  
  4386. Example of Usage:
  4387.             les di, FPValue
  4388.             ssfpa
  4389.  
  4390. Description:    SSFPA stores the floating point accumulator into a single
  4391.         precision variable in memory (pointed at by ES:DI).  It
  4392.         converts the value from the 81-bit format to the 32-bit
  4393.         value before storing the result.   The 64-bit mantissa used
  4394.         by the FP package is rounded to 24 bits during the store.
  4395.         The exponent could be out of range.  If this occurs, SSFPA
  4396.         returns with the carry flag set.
  4397.  
  4398. Include:    stdlib.a or fp.a
  4399.  
  4400.  
  4401. Routine:  ldfpa
  4402. ---------------
  4403.  
  4404. Category:             Floating point Routine
  4405.  
  4406. Registers on entry:   ES:DI points at a double precision (64-bit) value to load
  4407.  
  4408. Registers on return:  None
  4409.  
  4410. Flags affected:       None
  4411.  
  4412. Example of Usage:
  4413.             les di, FPValue
  4414.             ldfpa
  4415.  
  4416. Description:    LDFPA loads a double precision floating point value into the
  4417.         internal floating point accumulator.  It also converts the
  4418.         64-bit format to the internal 81-bit format used by the
  4419.         floating point package.
  4420.  
  4421. Include:    stdlib.a or fp.a
  4422.  
  4423. Routine:  sdfpa
  4424. ---------------
  4425.  
  4426. Category:             Floating point Routine
  4427.  
  4428. Registers on entry:   ES:DI points at a double precision (64-bit) value where
  4429.               this routine should store the floating point acc.
  4430.  
  4431. Registers on return:  None
  4432.  
  4433. Flags affected:       Carry set if conversion error.
  4434.  
  4435. Example of Usage:
  4436.             les di, FPValue
  4437.             sdfpa
  4438.  
  4439. Description:    SDFPA stores the floating point accumulator into a double
  4440.         precision variable in memory (pointed at by ES:DI).  It
  4441.         converts the value from the 81-bit format to the 64-bit
  4442.         value before storing the result.   The 64-bit mantissa used
  4443.         by the FP package is rounded to 51 bits during the store.
  4444.         The exponent could be out of range.  If this occurs, SDFPA
  4445.         returns with the carry flag set.
  4446.  
  4447. Include:    stdlib.a or fp.a
  4448.  
  4449.  
  4450. Routine:  lefpa
  4451. ---------------
  4452.  
  4453. Category:             Floating point Routine
  4454.  
  4455. Registers on entry:   ES:DI points at an extended precision (80-bit) value to
  4456.               load
  4457.  
  4458. Registers on return:  None
  4459.  
  4460. Flags affected:       None
  4461.  
  4462. Example of Usage:
  4463.             les di, FPValue
  4464.             lefpa
  4465.  
  4466. Description:    LEFPA loads an extended precision floating point value into
  4467.         the internal floating point accumulator.  It also converts the
  4468.         80-bit format to the internal 81-bit format used by the
  4469.         floating point package.
  4470.  
  4471. Include:    stdlib.a or fp.a
  4472.  
  4473.  
  4474. Routine:  lefpal
  4475. ----------------
  4476.  
  4477. Category:             Floating point Routine
  4478.  
  4479. Registers on entry:   CS:RET points at an extended precision (80-bit) value to
  4480.               load
  4481.  
  4482. Registers on return:  None
  4483.  
  4484. Flags affected:       None
  4485.  
  4486. Example of Usage:
  4487.             lefpal
  4488.             dt    1.345e-3
  4489.  
  4490. Description:    LEFPAL loads an extended precision floating point value into
  4491.         the internal floating point accumulator.  It also converts the
  4492.         80-bit format to the internal 81-bit format used by the
  4493.         floating point package.
  4494.  
  4495.         Unlike LEFPA, LEFPAL gets its operand directly from the code
  4496.         stream.  You must follow the call to lefpal with a ten-byte
  4497.         (80-bit) floating point constant.
  4498. Include:    stdlib.a or fp.a
  4499.  
  4500. Routine:  sefpa
  4501. ---------------
  4502.  
  4503. Category:             Floating point Routine
  4504.  
  4505. Registers on entry:   ES:DI points at an extended precision (80-bit) value
  4506.               where this routine should store the floating point acc.
  4507.  
  4508. Registers on return:  None
  4509.  
  4510. Flags affected:       Carry set if conversion error.
  4511.  
  4512. Example of Usage:
  4513.             les di, FPValue
  4514.             sefpa
  4515.  
  4516. Description:    SEFPA stores the floating point accumulator into an extended
  4517.         precision variable in memory (pointed at by ES:DI).  It
  4518.         converts the value from the 81-bit format to the 80-bit
  4519.         value before storing the result.
  4520.  
  4521.         The exponent could be out of range.  If this occurs, SEFPA
  4522.         returns with the carry flag set.
  4523.  
  4524. Include:    stdlib.a or fp.a
  4525.  
  4526.  
  4527. Routine:  lsfpo
  4528. ---------------
  4529.  
  4530. Category:             Floating point Routine
  4531.  
  4532. Registers on entry:   ES:DI points at a single precision (32-bit) value to load
  4533.  
  4534. Registers on return:  None
  4535.  
  4536. Flags affected:       None
  4537.  
  4538. Example of Usage:
  4539.             les di, FPValue
  4540.             lsfpo
  4541.  
  4542. Description:    LSFPA loads a single precision floating point value into the
  4543.         internal floating point operand.  It also converts the
  4544.         32-bit format to the internal 81-bit format used by the
  4545.         floating point package.
  4546.  
  4547. Include:    stdlib.a or fp.a
  4548.  
  4549.  
  4550. Routine:  ldfpo
  4551. ---------------
  4552.  
  4553. Category:             Floating point Routine
  4554.  
  4555. Registers on entry:   ES:DI points at a double precision (64-bit) value to load
  4556.  
  4557. Registers on return:  None
  4558.  
  4559. Flags affected:       None
  4560.  
  4561. Example of Usage:
  4562.             les di, FPValue
  4563.             ldfpo
  4564.  
  4565. Description:    LDFPO loads a double precision floating point value into the
  4566.         internal floating point operand.  It also converts the
  4567.         64-bit format to the internal 81-bit format used by the
  4568.         floating point package.
  4569.  
  4570. Include:    stdlib.a or fp.a
  4571.  
  4572.  
  4573. Routine:  lefpo
  4574. ---------------
  4575.  
  4576. Category:             Floating point Routine
  4577.  
  4578. Registers on entry:   ES:DI points at an extended precision (80-bit) value to
  4579.               load
  4580.  
  4581. Registers on return:  None
  4582.  
  4583. Flags affected:       None
  4584.  
  4585. Example of Usage:
  4586.             les di, FPValue
  4587.             lefpo
  4588.  
  4589. Description:    LEFPO loads an extended precision floating point value into
  4590.         the internal floating point operand.  It also converts the
  4591.         80-bit format to the internal 81-bit format used by the
  4592.         floating point package.
  4593.  
  4594. Include:    stdlib.a or fp.a
  4595.  
  4596.  
  4597. Routine:  lefpol
  4598. ----------------
  4599.  
  4600. Category:             Floating point Routine
  4601.  
  4602. Registers on entry:   CS:RET points at an extended precision (80-bit) value to
  4603.               load
  4604.  
  4605. Registers on return:  None
  4606.  
  4607. Flags affected:       None
  4608.  
  4609. Example of Usage:
  4610.             lefpal
  4611.             dt    1.345e-3
  4612.  
  4613. Description:    LEFPOL loads an extended precision floating point value into
  4614.         the internal floating point operand.  It also converts the
  4615.         80-bit format to the internal 81-bit format used by the
  4616.         floating point package.
  4617.  
  4618.         Unlike LEFPO, LEFPOL gets its operand directly from the code
  4619.         stream.  You must follow the call to lefpal with a ten-byte
  4620.         (80-bit) floating point constant.
  4621. Include:    stdlib.a or fp.a
  4622.  
  4623.  
  4624. Routine:  itof
  4625. --------------
  4626.  
  4627. Category:             Floating point Routine
  4628.  
  4629. Registers on entry:   AX contains a signed integer value
  4630.  
  4631. Registers on return:  None
  4632.  
  4633. Flags affected:       None
  4634.  
  4635. Example of Usage:
  4636.             mov    ax, -1234
  4637.             itof
  4638.  
  4639. Description:    ITOF converts the 16-bit signed integer in AX to a floating
  4640.         point value, storing the result in the floating point
  4641.         accumuator.
  4642.  
  4643. Include:    stdlib.a or fp.a
  4644.  
  4645.  
  4646. Routine:  utof
  4647. --------------
  4648.  
  4649. Category:             Floating point Routine
  4650.  
  4651. Registers on entry:   AX contains an unsigned integer value
  4652.  
  4653. Registers on return:  None
  4654.  
  4655. Flags affected:       None
  4656.  
  4657. Example of Usage:
  4658.             mov    ax, -1234
  4659.             itof
  4660.  
  4661. Description:    UTOF converts the 16-bit unsigned integer in AX to a floating
  4662.         point value, storing the result in the floating point
  4663.         accumuator.
  4664.  
  4665. Include:    stdlib.a or fp.a
  4666.  
  4667.  
  4668. Routine:  ultof
  4669. ---------------
  4670.  
  4671. Category:             Floating point Routine
  4672.  
  4673. Registers on entry:   DX:AX contains an unsigned 32-bit integer value
  4674.  
  4675. Registers on return:  None
  4676.  
  4677. Flags affected:       None
  4678.  
  4679. Example of Usage:
  4680.             mov    dx, word ptr val32+2
  4681.             mov    ax, word ptr val32
  4682.             ultof
  4683.  
  4684. Description:    ULTOF converts the 32-bit unsigned integer in DX:AX to a
  4685.         floating point value, storing the result in the floating
  4686.         point accumuator.
  4687.  
  4688. Include:    stdlib.a or fp.a
  4689.  
  4690.  
  4691. Routine:  ltof
  4692. --------------
  4693.  
  4694. Category:             Floating point Routine
  4695.  
  4696. Registers on entry:   DX:AX contains a signed 32-bit integer value
  4697.  
  4698. Registers on return:  None
  4699.  
  4700. Flags affected:       None
  4701.  
  4702. Example of Usage:
  4703.             mov    dx, word ptr val32+2
  4704.             mov    ax, word ptr val32
  4705.             ltof
  4706.  
  4707. Description:    LTOF converts the 32-bit signed integer in DX:AX to a
  4708.         floating point value, storing the result in the floating
  4709.         point accumuator.
  4710.  
  4711. Include:    stdlib.a or fp.a
  4712.  
  4713.  
  4714. Routine:  ftoi
  4715. --------------
  4716.  
  4717. Category:             Floating point Routine
  4718.  
  4719. Registers on entry:   None
  4720.  
  4721. Registers on return:  AX contains 16-bit signed integer
  4722.  
  4723. Flags affected:       Carry is set if conversion error occurs.
  4724.  
  4725. Example of Usage:
  4726.             ftoi
  4727.             puti        ;Print AX as integer value
  4728.  
  4729.  
  4730. Description:    FTOI converts the floating point accumulator value to a
  4731.         16-bit signed integer and returns the result in AX.  If
  4732.         the floating point number will not fit in AX, FTOI returns
  4733.         with the carry flag set.
  4734.  
  4735. Include:    stdlib.a or fp.a
  4736.  
  4737.  
  4738. Routine:  ftou
  4739. --------------
  4740.  
  4741. Category:             Floating point Routine
  4742.  
  4743. Registers on entry:   None
  4744.  
  4745. Registers on return:  AX contains 16-bit unsigned integer
  4746.  
  4747. Flags affected:       Carry is set if conversion error occurs.
  4748.  
  4749. Example of Usage:
  4750.             ftou
  4751.             putu        ;Print AX as an unsigned value
  4752.  
  4753.  
  4754. Description:    FTOU converts the floating point accumulator value to a
  4755.         16-bit unsigned integer and returns the result in AX.  If
  4756.         the floating point number will not fit in AX, FTOU returns
  4757.         with the carry flag set.
  4758.  
  4759. Include:    stdlib.a or fp.a
  4760.  
  4761.  
  4762. Routine:  ftol
  4763. --------------
  4764.  
  4765. Category:             Floating point Routine
  4766.  
  4767. Registers on entry:   None
  4768.  
  4769. Registers on return:  DX:AX contains a 32-bit signed integer
  4770.  
  4771. Flags affected:       Carry is set if conversion error occurs.
  4772.  
  4773. Example of Usage:
  4774.             ftol
  4775.             putl        ;Print DX:AX as integer value
  4776.  
  4777.  
  4778. Description:    FTOL converts the floating point accumulator value to a
  4779.         32-bit signed integer and returns the result in DX:AX.  If
  4780.         the floating point number will not fit in DX:AX, FTOL returns
  4781.         with the carry flag set.
  4782.  
  4783. Include:    stdlib.a or fp.a
  4784.  
  4785.  
  4786. Routine:  ftoul
  4787. ---------------
  4788.  
  4789. Category:             Floating point Routine
  4790.  
  4791. Registers on entry:   None
  4792.  
  4793. Registers on return:  DX:AX contains a 32-bit unsigned integer
  4794.  
  4795. Flags affected:       Carry is set if conversion error occurs.
  4796.  
  4797. Example of Usage:
  4798.             ftoul
  4799.             putul        ;Print DX:AX as an integer value
  4800.  
  4801.  
  4802. Description:    FTOUL converts the floating point accumulator value to a
  4803.         32-bit unsigned integer and returns the result in DX:AX.  If
  4804.         the floating point number will not fit in DX:AX, FTOUL returns
  4805.         with the carry flag set.
  4806.  
  4807. Include:    stdlib.a or fp.a
  4808.  
  4809.  
  4810. Routine:  fpadd
  4811. ---------------
  4812.  
  4813. Category:             Floating point Routine
  4814.  
  4815. Registers on entry:   None
  4816.  
  4817. Registers on return:  None
  4818.  
  4819. Flags affected:       None
  4820.  
  4821. Example of Usage:
  4822.             fpadd
  4823.  
  4824. Description:    FPADD adds the floating point operand to the floating point
  4825.         accumulator leaving the result in the floating point
  4826.         accumulator.
  4827.  
  4828. Include:    stdlib.a or fp.a
  4829.  
  4830.  
  4831. Routine:  fpsub
  4832. ---------------
  4833.  
  4834. Category:             Floating point Routine
  4835.  
  4836. Registers on entry:   None
  4837.  
  4838. Registers on return:  None
  4839.  
  4840. Flags affected:       None
  4841.  
  4842. Example of Usage:
  4843.             fpsub
  4844.  
  4845. Description:    FPSUB subtracts the floating point operand from the floating
  4846.         point accumulator leaving the result in the floating point
  4847.         accumulator.
  4848.  
  4849. Include:    stdlib.a or fp.a
  4850.  
  4851.  
  4852. Routine:  fpcmp
  4853. ---------------
  4854.  
  4855. Category:             Floating point Routine
  4856.  
  4857. Registers on entry:   None
  4858.  
  4859. Registers on return:  AX contains result of comparison.
  4860.  
  4861. Flags affected:       As appropriate for a comparison.  You can use the
  4862.               conditional branches to check the comparison after
  4863.               calling this routine.  Be sure to use the *signed*
  4864.               conditional jumps (e.g., JG, JGE, etc.).
  4865.  
  4866. Example of Usage:
  4867.             fpcmp
  4868.             jge    FPACCgeFPOP
  4869.  
  4870. Description:    FPCMP compares the floating point accumulator to the
  4871.         floating point operand and sets the flags according to the
  4872.         result of the comparison.  It also returns a value in AX
  4873.         as follows:
  4874.  
  4875.             AX    Result
  4876.             -1    FPACC < FPOP
  4877.              0    FPACC = FPOP
  4878.              1    FPACC > FPOP
  4879.  
  4880. Include:    stdlib.a or fp.a
  4881.  
  4882.  
  4883. Routine:  fpmul
  4884. --------------
  4885.  
  4886. Category:             Floating point Routine
  4887.  
  4888. Registers on entry:   None
  4889.  
  4890. Registers on return:  None
  4891.  
  4892. Flags affected:       None
  4893.  
  4894. Example of Usage:
  4895.             fpmul
  4896.  
  4897. Description:    FPMUL multiplies the floating point accumulator by the floating
  4898.         point operand and leaves the result in the floating point
  4899.         accumulator.
  4900.  
  4901. Include:    stdlib.a or fp.a
  4902.  
  4903.  
  4904. Routine:  fpdiv
  4905. ---------------
  4906.  
  4907. Category:             Floating point Routine
  4908.  
  4909. Registers on entry:   None
  4910.  
  4911. Registers on return:  None
  4912.  
  4913. Flags affected:       None
  4914.  
  4915. Example of Usage:
  4916.             fpdiv
  4917.  
  4918. Description:    FPDIV divides the floating point accumulator by the floating
  4919.         point operand and leaves the result in the floating point
  4920.         accumulator.
  4921.  
  4922. Include:    stdlib.a or fp.a
  4923.  
  4924.  
  4925. Routine:  ftoa (2,m)
  4926. --------------------
  4927.  
  4928. Category:             Floating point Routine
  4929.  
  4930. Registers on entry:   ES:DI points at buffer to hold result (ftoa/ftoa2 only)
  4931.               AL- Field width for floating point value.
  4932.               AH- Number of positions to the right of the dec pt.
  4933.  
  4934. Registers on return:  ES:DI points at beginning of string (ftoa/ftoam only)
  4935.               ES:DI points at zero terminating byte (ftoa2 only)
  4936.  
  4937. Flags affected:       Carry is set if malloc error (ftoam only)
  4938.  
  4939. Example of Usage:
  4940.             mov    di, seg buffer
  4941.             mov    es, di
  4942.             lea    di, buffer
  4943.             mov    ah, 2        ;Two digits after "."
  4944.             mov    al, 10        ;Use a total of ten positions
  4945.             ftoa
  4946.  
  4947.  
  4948.  
  4949. Description:    FTOA (2,M) converts the value in the floating point accumulator
  4950.         to a string of characters which represent that value.  These
  4951.         routines use a decimal representation.  The value in AH is
  4952.         the number of digits to put after the decimal point, AL
  4953.         contains the total field width (including room for the sign
  4954.         and decimal point).  The field width specification works
  4955.         just like Pascal or FORTRAN.  If the number will not fit in
  4956.         the specified field width, FTOA outputs a bunch of "#"
  4957.         characters.
  4958.  
  4959.         FTOA stores the converted string at the address specified by
  4960.         ES:DI upon entry.  There must be at least AL+1 bytes at this
  4961.         address.  It returns with ES:DI pointing at the start of this
  4962.         buffer.
  4963.  
  4964.         FTOA2 works just like FTOA except it does not preserve DI.
  4965.         It returns with DI pointing at the zero terminating byte.
  4966.  
  4967.         FTOAM allocates storage for the string on the heap and returns
  4968.         a pointer to the converted string in ES:DI.
  4969.  
  4970.         Note: this routine preserves the value in the floating point
  4971.         accumulator but it wipes out the value in the floating point
  4972.         operand.
  4973.  
  4974. Include:    stdlib.a or fp.a
  4975.  
  4976.  
  4977. Routine:  etoa (2,m)
  4978. --------------------
  4979.  
  4980. Category:             Floating point Routine
  4981.  
  4982. Registers on entry:   ES:DI points at buffer to hold result (etoa/etoa2 only)
  4983.               AL- Field width for floating point value.
  4984.  
  4985. Registers on return:  ES:DI points at beginning of string (etoa/etoam only)
  4986.               ES:DI points at zero terminating byte (etoa2 only)
  4987.  
  4988. Flags affected:       Carry is set if malloc error (etoam only)
  4989.  
  4990. Example of Usage:
  4991.             mov    al, 14        ;Use a total of 14 positions
  4992.             etoam
  4993.             puts
  4994.             putcr
  4995.             free
  4996.  
  4997.  
  4998.  
  4999. Description:    ETOA (2,M) converts the value in the floating point accumulator
  5000.         to a string of characters which represent that value.  These
  5001.         routines use an exponential (scientific notation)
  5002.         representation.  AL contains the field width.  It contains
  5003.         the number of print position to use when outputting the
  5004.         number.  The field width specification works just like Pascal
  5005.         or FORTRAN.  If the number will not fit in the specified
  5006.         field width, ETOA outputs a bunch of "#" characters.
  5007.  
  5008.         ETOA stores the converted string at the address specified by
  5009.         ES:DI upon entry.  There must be at least AL+1 bytes at this
  5010.         address.  It returns with ES:DI pointing at the start of this
  5011.         buffer.
  5012.  
  5013.         ETOA2 works just like ETOA except it does not preserve DI.
  5014.         It returns with DI pointing at the zero terminating byte.
  5015.  
  5016.         ETOAM allocates storage for the string on the heap and returns
  5017.         a pointer to the converted string in ES:DI.
  5018.  
  5019.         Note: this routine preserves the value in the floating point
  5020.         accumulator but it wipes out the value in the floating point
  5021.         operand.
  5022.  
  5023. Include:    stdlib.a or fp.a
  5024.  
  5025.  
  5026. Routine:  atof
  5027. --------------
  5028.  
  5029. Category:             Floating point Routine
  5030.  
  5031. Registers on entry:   ES:DI points at a string containing the representation
  5032.               of a floating point number in ASCII form.
  5033.  
  5034. Registers on return:  None
  5035.  
  5036. Flags affected:       None
  5037.  
  5038. Example of Usage:
  5039.             les    di, FPStr
  5040.             atof
  5041.  
  5042.  
  5043. Description:    ATOF converts the string pointed at by ES:DI into a floating
  5044.         point value and leaves this value in the floating point
  5045.         accumulator.  Legal floating point values are described
  5046.         by the following regular expression:
  5047.  
  5048.  
  5049.         {" "}* {+ | -} ( ([0-9]+ {"." [0-9]*}) | ("." [0-9]+)}
  5050.                 {(e | E) {+ | -} [0-9] {[0-9]*}}
  5051.  
  5052.  "{}" denote optional items.
  5053.  "|"  denotes OR.
  5054.  "()" groups items together.
  5055.  
  5056.  
  5057.  
  5058. Include:    stdlib.a or fp.a
  5059.  
  5060.  
  5061.  
  5062. ******************************************************************************
  5063.  
  5064.         File I/O Routines
  5065.  
  5066.            Featuring:
  5067.                - Opening and closing files
  5068.                - Creating new files
  5069.                - Deleting files
  5070.                - Renaming files
  5071.                - File "seeking"
  5072.                - Blocked I/O:
  5073.                    - Reading from files using getc
  5074.                    - Writing to files using putc and puts
  5075.                    - File flushing
  5076.  
  5077. ******************************************************************************
  5078.  
  5079.            Written by:
  5080.  
  5081.                Mark Radleigh
  5082.                &
  5083.  
  5084.                Brian Harvey
  5085.  
  5086. ******************************************************************************
  5087.  
  5088.  
  5089. fcreate
  5090. *    Creates a new file.
  5091. *    If a file already exists with the requested name, it will be deleted
  5092.     and a new one will take its place.
  5093. Inputs: ES:DI- Contains address of the filename for the new file
  5094. Outputs: AX- If no error occured in creating the file, it contains a
  5095.         filehandle number assigned to this file by DOS.
  5096.          If an error has occurred, it contains one of the following error
  5097.         codes:
  5098.          3 - Path not found
  5099.          4 - Too many open files
  5100.          5 - Access denied
  5101.      Carry flag- 0 if no error occured, 1 if error
  5102. Include:    Stdlib.a or files.a
  5103. Updated:    6/14/91        First public release
  5104.  
  5105. This routine creates a new file on the specified pathname. If no pathname or
  5106. device is specified, the file will be created in the current working directory.
  5107. If the file has been successfully created (No errors occured!), then this
  5108. routine returns in the ax register a number that is the DOS filehandle for
  5109. this file. Don't lose this value. You will need it when to want to close the
  5110. file (using fclose). Save the ax register in a variable after the routine call
  5111. and move the variable back into the ax register before you call the fclose
  5112. stdlib routine. See documentation for fclose for more information.
  5113.  
  5114. FILEHANDLE NOTICE: The filehandle returned in the ax register is not the true
  5115. DOS filehandle for this file. However, this filehandle is too be used when
  5116. calling the file routines in stdlib. In order to get the true filehandle for a
  5117. certain file, see the documentation for the stdlib routine, DOSHandle
  5118.  
  5119. Example:
  5120.  
  5121.         print
  5122.         db      "What do you desire to create?",0
  5123.         gets                            ;Get filename and store in es:di
  5124.         fcreate                      ;Call routine to create file
  5125.         jc      error                   ;If the carry flag is set,
  5126.                         ;an error has occured.
  5127.         mov     fileptr, ax             ;Save the filehandle stored in
  5128.                         ;the ax register for future
  5129.                         ;use
  5130.  
  5131. fopen
  5132. *    Opens a file for reading or writing.
  5133. *    File I/O depends on value in the al register.
  5134. Inputs: ES:DI- Contains address of the filename for the file to be opened
  5135.     AL- Contains 0 if the file is to be opened for reading.
  5136.         Contains 1 if the file is to be opened for writing.
  5137. Outputs: AX- If no error occured in opening the file, it contains a
  5138.         filehandle number assigned to this file by DOS.
  5139.          If an error has occured, it contains one of the following error
  5140.         codes:
  5141.          2 - File not found
  5142.          4 - Too many open files
  5143.          5 - Access denied
  5144.          12 - Invalid access
  5145.      Carry flag- 0 if no error occured, 1 if error
  5146. Include:    Stdlib.a or files.a
  5147. Updated:    6/14/91        First public release
  5148.  
  5149. This routine opens a file for reading or writing using the specified filename
  5150. and directory (any standard DOS file pathway) in ES:DI. Using the stdlib gets
  5151. routine is an excellent and advisable way (Not to mention an easy way!) of
  5152. getting the filename in ES:DI. The user must also move one of two values into
  5153. the al register before calling fopen. To open a file for reading, the al
  5154. register must contain the value 0 and to open a file for writing, the al
  5155. register must contain the value 1. If the file has been successfully opened, a
  5156. filehandle for this file assigned by DOS. Save this filehandle in some sort of
  5157. variable so you can move it back into the ax register when you call the stdlib
  5158. routine fclose to close the file. See documentation for fclose for more
  5159. information. Examine the examples below for a suggested way of saving the
  5160. filehandle (the example uses a variable called fileptr, but the name is
  5161. arbritary).
  5162.  
  5163. FILEHANDLE NOTICE: The filehandle returned in the ax register is not the true
  5164. DOS filehandle for this file. However, this filehandle is too be used when
  5165. calling the file routines in stdlib. In order to get the true filehandle for a
  5166. certain file, see the documentation for the stdlib routine, DOSHandle
  5167.  
  5168. NOTICE FOR MULTIPLE OPEN FILES: fopen, along with fcreate and fclose, allows the
  5169.                 user have up to 10 files open at the same time.
  5170.                 In order to keep track of all the filehandles of
  5171.                 these open files, it is suggested that a
  5172.                 separate variable for the filehandle of each
  5173.                 of the open files be used to keep track of the
  5174.                 handles.
  5175.  
  5176. Example for opening mulitple files (same theory applies with fcreate):
  5177.         print
  5178.         db      "What do you desire to open?",0
  5179.         gets                            ;Get filename and store in es:di
  5180.         mov     al, 1                   ;1 so the file will be opened
  5181.                         ;for writing
  5182.         fopen                        ;Call routine to open file
  5183.         jc      error                   ;If the carry flag is set,
  5184.                         ;an error has occured, so quit!
  5185.         mov     fileptr, ax             ;Save the filehandle stored in
  5186.                         ;the ax register for future
  5187.                         ;use
  5188.         print
  5189.         db    "What is the 2nd file you wish to open?",0
  5190.         gets
  5191.         mov    al, 1
  5192.         fopen                ;Open 2nd file for writing
  5193.         jc    error            ;Error??
  5194.         mov    fileptr2,ax        ;Save the filehandle for the 2nd
  5195.                         ;open file in a separate
  5196.                         ;variable
  5197.  
  5198.  
  5199. Warning:  If the file the user wishes to open already exists and the user wants
  5200.       to open it for writing, then the data written to the file will
  5201.       overwrite the pre-exeisting data. See docs for fseek to overcome
  5202.       this problem.
  5203.  
  5204. Example:
  5205.  
  5206. ;Open a file for writing
  5207.         print
  5208.         db      "What do you desire to open?",0
  5209.         gets                            ;Get filename and store in es:di
  5210.         mov    al, 1            ;1 so the file will be opened
  5211.                         ;for writing
  5212.  
  5213.  
  5214.         fopen                        ;Call routine to open file
  5215.         jc      error                   ;If the carry flag is set,
  5216.                         ;an error has occured, so quit!
  5217.         mov     fileptr, ax             ;Save the filehandle stored in
  5218.                         ;the ax register for future
  5219.                         ;use
  5220.  
  5221. ;Open a file for reading
  5222.         print
  5223.         db      "What do you desire to open?",0
  5224.         gets                            ;Get filename and store in es:di
  5225.         mov     al, 0                   ;0 so the file will be opened
  5226.                         ;for reading
  5227.                 fopen                        ;Call routine to open file
  5228.                 jc      error                   ;If the carry flag is set,
  5229.                                                 ;an error has occured, so quit!
  5230.         mov     fileptr, ax             ;Save the filehandle stored in
  5231.                                                 ;the ax register for future
  5232.                                                 ;use
  5233.  
  5234. fclose
  5235. *    Closes an open file
  5236. *    Filehandle for file to be closed needs to be in the ax register
  5237. Input: AX- Contains the filehandle variable of the file to close.
  5238. Outputs: AX- If carry flag is set (error occured), then ax contains an error
  5239.         code.
  5240.          If an error has occured, it contains the following error code:
  5241.         6 - Invalid file handle
  5242.         10 - Trouble with FREE (memory freeing routine)
  5243.      Carry flag- 0 if no error occured, 1 if error.
  5244. Include:    Stdlib.a or files.a
  5245. Updated:    6/14/91        First public release
  5246.  
  5247. This routine closes an open file. Once the file is closed no I/O processes
  5248. can be made on the file. Before calling the routine, fclose, the user must
  5249. move into the ax register the filehandle assigned to this file when the file
  5250. was opened or created. The only error that can occur is if the user moved into
  5251. the ax register a filehandle that does not belong to one of the opened files.
  5252. The following example demonstrates how to close a file that was opened in one of
  5253. the fopen examples or the file that was created in the fcreate example, whose
  5254. filehandle was saved in variable called fileptr.
  5255. Example:
  5256.                 mov     ax, fileptr        ;Move the DOS filehandle into
  5257.                         ;the ax register before
  5258.                         ;calling routine
  5259.                 fclose                ;Close the file
  5260.                 cmp     ax, 6            ;If the filehandle was an
  5261.                         ;invalid filehandle jump to
  5262.                         ;user's code for error's
  5263.                 je      error
  5264. ;The following code is a continuation in the case that multiple files are
  5265. ;open. The code close the second open file.
  5266.         mov    ax, fileptr2
  5267.         fclose
  5268.         cmp    ax, 6
  5269.         je    error
  5270.  
  5271. fwriteon
  5272. *    Turns on the write to file mode.
  5273. *    Redirects the ouput of stdlib routines putc and puts to a open file
  5274. Input: AX- Contains the filehandle of which open file to write data to.
  5275. Outputs: AX- If an error occurs in attempting to write to a file, ax will
  5276.         contain one of the following error codes:
  5277.           5 - Accessed denied
  5278.           6 - Invalid handle
  5279.      Carry flag- 0 if no error occured, 1 if error.
  5280. Include:    Stdlib.a or files.a
  5281. Updated:    6/14/91        First public release
  5282.  
  5283. This routine turns the write to disk mode on. In other words, it redirects the
  5284. output of the stdlib putc routine so that instead of writing data to the screen,
  5285. the data is written to the file whose filehandle is in the ax register when
  5286. fwriteon is called. The routine that replaces the output device of putc's ouput
  5287. actually uses what is known as Blocked I/O. Instead of writing one character
  5288. to the file each time the user calls getc, each character is stored in a buffer
  5289. in memory. When the buffer contains 256 characters, that buffer is written to
  5290. the file as a block. The buffer is then cleared and more characters can be read
  5291. with getc. Using blocked I/O is a lot faster than one character at a time. Along
  5292. with getc, the stdlib routine gets' ouput is also redirected during fwriteon
  5293. mode, since in the stdlib, gets actually just calls getc many times.
  5294.  
  5295. Example:
  5296. ;This code would appear in a program after a file has been created or opened
  5297. ;for "gets"
  5298.         mov    ax, fileptr        ;Move into ax filehandle of
  5299.                         ;file to write to
  5300.                 fwriteon                     ;Call function to redirect
  5301.                                                 ;the output of putc and puts
  5302.         puts
  5303.         fwriteoff            ;Turn off write to disk mode
  5304.         puts
  5305. ;The puts must appear after the fwriteoff command because gets automatically
  5306. ;writes whatever is in ES:DI to the screen (or in this case the file). The puts
  5307. ;appearing after the writeoff, prints whatever is at ES:DI to the screen. If
  5308. ;the puts were to appear in the writeoon mode, the string at ES:DI would be
  5309. ;written to the file twice
  5310.  
  5311. Example:
  5312. ;This code would appear in a program after a file has been created or opened
  5313. ;for "getc"
  5314.         mov    ax, fileptr        ;Move into ax filehandle of
  5315.                         ;file to write to
  5316.         fwriteon                 ;Call function to redirect
  5317.                         ;the output of putc and puts
  5318.         getc
  5319.         putc
  5320.         fwriteoff
  5321. ;Unlike in the previous example, getc and putc may both appear in the writeon
  5322. ;mode. The getc will get a character from the keyboard and store it in the al
  5323. ;register. Putc will then write whatever is in the al register to the
  5324. ;specified open file. In order for the user to see what character they typed
  5325. ;in, in the previous example, a putc should appear after the fwriteoff call.
  5326. ;Since fwriteoff redirects the putc ouput back to normal (See docs for fwriteoff
  5327. ;for more info) the character in al will be put on the screen.
  5328.  
  5329. fwriteoff
  5330. *    Turns off the write to file mode
  5331. *    Redirects the output of putc back to normal (the screen!)
  5332.         mode.
  5333. Include:    Stdlib.a or files.a
  5334. Updated:    6/14/91        First public release
  5335.  
  5336. This routines changes or redirects the ouput of stdlib's putc back to normal.
  5337. In other words, since the routine fwriteon made the ouput go to a disk file,
  5338. changing it back to normal means that after this routine is called, all putc's
  5339. used will print whatever is in the al register to the screen.
  5340.  
  5341. Example:
  5342. ;This example gets a character from the keyboard, prints to a disk file and then
  5343. ;prints to the screen the character in the al register that was entered.
  5344.         mov    ax, fileptr        ;Move into ax filehandle of
  5345.                         ;file to write to
  5346.         fwriteon                 ;Call function to redirect
  5347.                         ;the output of putc and puts
  5348.         getc                ;Get character and store in al
  5349.         putc                ;Print character in al to file
  5350.         fwriteoff            ;Change ouput of putc back to
  5351.                         ;normal
  5352.         putc                ;Prints character in al to
  5353.                         ;screen
  5354. fflush
  5355. *    Flushes the buffer in an opened write file to that file
  5356. Inputs:    AX- Contains Stdlib filehandle of file whose buffer is to be flushed
  5357. Outputs: None.
  5358. Include:    Stdlib.a or files.a
  5359. Updated:        6/14/91         First public release
  5360.  
  5361. This routine takes all data from the buffer associated with the Stdlib
  5362. filehandle passed in AX and writes it to the file. It then clears the buffer.
  5363. NOTE: This routine is automatically called on by Fclose.
  5364.  
  5365. freadon
  5366. *    Turns on the read from file mode
  5367. *    Changes the source of the input for the stdlib function getc
  5368. Input:    AX- Contains the filehandle of which open file to read data from.
  5369. Output: AX- If an error occurs in attempting to read from a file, ax will
  5370.         contain one of the following error codes:
  5371.           5 - Access denied
  5372.           6 - Invalid handle
  5373.           8 - EOF
  5374.     Carry flag- 0 if no error occured, 1 if error.
  5375. Include:    Stdlib.a or files.a
  5376. Updated:    6/14/91        First public release
  5377.  
  5378. This routine turns the read from file mode on. It redirects the source from
  5379. which stdlib's getc routine gets its "character" from. Instead of getting the
  5380. character from the keyboard, the redirected getc reads a character from a opened
  5381. file. Actually, this routine uses the blocked I/O idea discussed in the writeon
  5382. documentation. This routine when called for the first time, meaning the buffer
  5383. for the current file to be read from is clear, will read it 256 characters from
  5384. (If there is that many) a file and store it in the buffer. The first character
  5385. in the buffer is then put in the al register for the user to then use for
  5386. whatever they wish. The next time the user calls getc (without calling the
  5387. freadoff rotuine yet) the next character in the buffer will be stored in the al
  5388. register. When the buffer is empty, another 256 bytes will be read into it. When
  5389. the routine freadoff is called, any getc routines called after that will get
  5390. a character from the keyboard.
  5391.  
  5392. Example:
  5393.         mov    ax, fileptr        ;Move the filehandle of the
  5394.                         ;file to read from into ax
  5395.         freadon                ;Turn on read mode!
  5396.         mov    cx, 10            ;Set up loop to read 10
  5397.                         ;characters from a file and
  5398.                         ;print them to the screen
  5399. loop1:        getc                ;Get character from buffer and
  5400.                         ;store in al
  5401.         jc    error            ;If error in reading from file
  5402.                         ;jump to user's code for
  5403.                         ;handling code
  5404.         putc                ;Print character in al to the
  5405.                         ;screen
  5406.         loop    loop1
  5407.         freadoff            ;turn read mode off from this
  5408.                         ;file
  5409.  
  5410. freadoff
  5411. *    Turns off the read from file mode
  5412. *    Redirects the source of the data for stdlib's getc routine back to
  5413.     normal
  5414.  
  5415. This routine changes the source from which stdlib's getc routine gets its
  5416. "character" from back to normal. After calling this routine, instead of reading
  5417. characters from the disk, using blocked I/O, the getc routine will get
  5418. it's "character" from the keyboard.
  5419.  
  5420. For code example of how to use freadoff, see the example of code above for
  5421. freadon.
  5422.  
  5423.  
  5424. fseek
  5425. *    Moves the file pointer of a file to anywhere in the file
  5426. Inputs:    SI- Contains the filehandle variable of the file to be used, or "seeked"
  5427.     AL- Contains the offset from where to start the file seeking.
  5428.         0 - Seek from the begining of the file.
  5429.         1 - Seek from current pointer position
  5430.         2 - Seek backwards from the end of file
  5431.     CX:DX- Distance to move in file, in bytes.
  5432. Outputs: DX:AX- Contains the new file position if no error
  5433.      AX- One of the following error codes if an error occured while
  5434.         "seeking":
  5435.           1 - Invalid function
  5436.           6 - Invalid handle
  5437.     Carry flag- 0 if no error occured, 1 if error.
  5438. Include:    Stdlib.a or files.a
  5439. Updated:    6/14/91        First public release
  5440.  
  5441. This routine allows the user the move the file pointer to any position within
  5442. a file. You can not move backwards in a file by having a negative value in
  5443. CX:DX. The value in CX:DX must be an unsigned integer. 
  5444.  
  5445. Example:
  5446.         mov    si, fileptr        ;Move the filehandle of the
  5447.                         ;file to be seeked
  5448.         mov    al, 0            ;Start moving pointer from
  5449.                         ;beginning of file
  5450.         xor    cx, cx            ;Clear the cx register
  5451.         mov    dx, 10            ;Move file pointer 10 bytes
  5452.                         ;into file
  5453.         fseek                ;Seek!!!
  5454.         jc    error            ;Jump to error code if error
  5455.  
  5456. To find out where the file pointer currently is in the file, first xor cx and 
  5457. dx registers and call fseek. It will return in DX:AX the file pointer's
  5458. position.
  5459.         mov    si, fileptr        ;Move the filehandle of the
  5460.                         ;file to be seeked
  5461.         mov    al, 1            ;Start moving pointer from
  5462.                         ;the current position
  5463.         xor    cx, cx            ;Clear the cx register
  5464.         xor    dx, dx            ;Clear the dx register
  5465.         fseek                ;Seek!!!
  5466.         jc    error            ;Jump to error code if error
  5467.                         ;else DX:AX contains the current
  5468.                         ;File pointer position.
  5469.  
  5470.  
  5471. DOSHandle
  5472. *    Returns in the ax register the true DOS filehandle for a file
  5473. Input:    AX- Contains the filehandle for the file given to the user from
  5474.         stdlib routine, fopen or fcreate
  5475. Ouputs:    AX- Contains the true filehandle given to the requested file by DOS
  5476.     AX- If an error occured, it contains the following error code:
  5477.           1 - Invalid pseudo-filehandle
  5478.     Carry flag- 0 if no error occured, 1 if error.
  5479. Include:    Stdlib.a or files.a
  5480. Updated:    6/14/91        First public release
  5481.  
  5482. This routine returns in the ax register the true filehandle variable given by
  5483. DOS for a particular file. The filehandle returned when calling the stdlib
  5484. functions, fcreate and fopen, is not the true filehandle for the file used
  5485. in those routines. The value returned is a value created by the routines, which
  5486. stores the filehandles for multiple files in a structure in memory. The value
  5487. returned from those functions is actually the index into the structure to the
  5488. real filehandle for the file. This function, DOSHandle, returns from this
  5489. structure in memory the actual filehandle for a file that has been opened. 
  5490. NOTICE: This routine is only useful to those who need to know the real
  5491. filehandle of a file that has been created or opened with fopen or fcreate. For
  5492. those who will only be using the File I/O routines provided in stdlib then
  5493. this routine will be of no importance. It is provided only for advanced assembly
  5494. language programmers who with to do other things with files and need to know
  5495. their real filehandle values.
  5496.  
  5497. Example:
  5498.         mov    ax, fileptr        ;Move into ax the filehandle
  5499.                         ;given to the user file fopen
  5500.                         ;or fcreate
  5501.         DOSHandle            ;Get the true filehandle for
  5502.                         ;a file and store it in the
  5503.                         ;ax register
  5504.         mov    truehandle, ax
  5505.  
  5506. frename
  5507. *    Renames a file
  5508. Input:    DX:SI- Contains the original pathname of the file
  5509.     ES:DI- Contains the new pathname of the file
  5510. Ouputs:    AX- Contains one of the following error codes if an error occured:
  5511.           2 - File not found
  5512.           5 - Access denied
  5513.           17 - Not the same device
  5514.     Carry flag- 0 if no error occured, 1 if error.
  5515. Include:    Stdlib.a or files.a
  5516. Updated:    6/14/91        First public release
  5517.  
  5518. This routine renames the file whose name appears in a string at DX:SI with the
  5519. name that appears at the string pointed at by ES:DI. If an error occurs, then
  5520. an appropriate error code appears in the ax register.
  5521.  
  5522. Example:
  5523.         print
  5524.         db    "Enter the source filename: ",0
  5525.         gets
  5526.         mov    dx, es
  5527.         mov    si, di
  5528.         print
  5529.         db    cr, lf, "Enter the new filename: ",0
  5530.         gets
  5531.         frename
  5532.         jc    error
  5533.  
  5534. fdel
  5535. *    Deletes a file
  5536. Input: ES:DI- Contains the address of zero terminated pathname of file
  5537. Output: AX- Contains one of the following error codes if an error occured:
  5538.           2 - File not found
  5539.           5 - Access denied
  5540.         Carry flag- 0 if no error occured, 1 if error.
  5541. Include:        Stdlib.a or files.a
  5542. Updated:        6/14/91         First public release
  5543.  
  5544. This routine deletes the filename that is in the string that ES:DI points to.
  5545.  
  5546. Example:
  5547.         print
  5548.         db    "Name of file to delete?",0
  5549.         gets
  5550.         fdel                ;Delete the file!
  5551.         jc    error            ;Jump to error code if an error
  5552.  
  5553.  
  5554.  
  5555.  
  5556. ======================
  5557. Miscellaneous Routines
  5558. ======================
  5559.  
  5560. This routines either defy categorization, or they haven't been properly
  5561. organized yet.
  5562.  
  5563. Mostly (like the rest of this library) they have simply been stuck here
  5564. until somebody gets the time to reorganize *everything*.
  5565.  
  5566.  
  5567.  
  5568.  
  5569. Routine:  Random
  5570. ----------------
  5571.  
  5572. Author:              Unknown.  Copied off a file on one of the networks,
  5573.               tweaked, and added to the library.  Any info on the
  5574.               original author would be appreciated.
  5575.  
  5576. Category:             Miscellaneous
  5577.  
  5578. Registers on entry:   None
  5579.  
  5580. Registers on return:  AX-    Contains random number
  5581.  
  5582. Flags affected:       None
  5583.  
  5584. Example of Usage:
  5585.             random    ;Generate random number in AX
  5586.             puti    ;Print the random number.
  5587.  
  5588.  
  5589. Description:    
  5590.  
  5591.  This routine computes a 16-bit random number each time you call it.  It
  5592. returns the random number in the AX register.  You may treat this as a signed
  5593. or unsigned value as it utilizes all 16 bits.  This code uses an internal
  5594. table of seed values.  If you are interested in producing repeatable sequences
  5595. of random numbers, please look at the source listings for this file.
  5596.  
  5597.  If you are interested in producing truly random values (well, closer than you
  5598. will get from this code by calling it right off the bat) look at the randomize
  5599. routine which tweaks the seed table based on the current time of day clock
  5600. value.
  5601.  
  5602. Include:    stdlib.a or misc.a
  5603.  
  5604.  
  5605. Routine:  Randomize
  5606. -------------------
  5607.  
  5608. Author:              Unknown.  Copied off a file on one of the networks,
  5609.               tweaked, and added to the library.  Any info on the
  5610.               original author would be appreciated.
  5611.  
  5612. Category:             Miscellaneous
  5613.  
  5614. Registers on entry:   None
  5615.  
  5616. Registers on return:  None
  5617.  
  5618. Flags affected:       None
  5619.  
  5620. Example of Usage:
  5621.             randomize    ;Randomize the seeds.
  5622.             random        ;Get a brand new random number
  5623.             puti        ;Print it
  5624.  
  5625. Description:    
  5626.  
  5627. Random's internal seed table is hard coded.  It was designed to produce a
  5628. sequence of random numbers with a very long period.  However, each time you
  5629. run a program using Random, it will generate the exact same sequence of
  5630. random numbers.  This could be distressing, for example, in a game where
  5631. after a while the player(s) could memorize some sequence of events based
  5632. on the random number generator.
  5633.  
  5634.  Randomize uses the time of day clock value to scramble the internal random
  5635. seed table.  If you call randomize before using random the first time, you
  5636. will generally get a different sequence of random numbers each time you
  5637. run the program.
  5638.  
  5639.  Note that it is dangerous to call randomize more than once inside any program.
  5640. The time of day clock is not a random source when invoked fairly often.
  5641. Furthermore, once the seeds are randomized, random does a pretty good job of
  5642. randomizing the results.
  5643.  
  5644. Include:    stdlib.a or misc.a
  5645.  
  5646.  
  5647. Routine:  cpuid
  5648. ---------------
  5649.  
  5650. Author:              Original implementation was supplied by Intel Corp.
  5651.               Various modifications were made for inclusion into
  5652.               the UCR Standard Library.
  5653.  
  5654. Category:             Miscellaneous
  5655.  
  5656. Registers on entry:   None
  5657.  
  5658. Registers on return:  AX-    Contains processor ID (86, 286, 386, or
  5659.                 486.  Note 8088=86).
  5660.  
  5661.               BX-    Contains coprocessor ID (87, 286, 387,
  5662.                 or 487).  Note that a true 486 will have
  5663.                 an 80487 built-in, 486sx chips, however, will
  5664.                 not.
  5665.  
  5666. Flags affected:       None
  5667.  
  5668. Example of Usage:
  5669.             cpuid
  5670.             cmp    ax, 8086    ;Is this an 8086?
  5671.  
  5672. Description:    
  5673.  
  5674.  For those programs which absolutely need to know the CPU in use, CPUID does
  5675. a reasonable job (in DOS real mode) of figuring this out for you.  As with
  5676. all CPU identification routines, there are bound to be some problems with this
  5677. one when operating in protected mode. But for normal DOS applications it
  5678. appears to work great.  This routine came straight from the horse's mouth
  5679. (Intel Corporation) so you can place a little more faith in it than most that
  5680. are floating around.  Intel's blessing doesn't guarantee that this routine
  5681. is perfect, though; always keep that in mind.
  5682.  
  5683. Include:    stdlib.a or misc.a
  5684.  
  5685.  
  5686. ===================
  5687. SmartArray Routines
  5688. ===================
  5689.  
  5690.   The SmartArray routines provide a consistent and easy to master interface to
  5691. vectors, matrices, and higher-dimension arrays.  It is a weak attempt at an
  5692. abstract, encapsulated, array data type (weak because the internal structure
  5693. is still visible, indeed, intended to be visible, to the main program).  These
  5694. routines include many operations stolen from the APL programming language.  As
  5695. such, they comprise a powerful set of matrix operations.  On the other hand,
  5696. because of their generality, they do not perform as quickly as hand-optimized
  5697. code doing the same thing.  These routines definitely represent a trade-off
  5698. between ease of use and performance.  That is not to say that these routines
  5699. are all slow.  Some operations, like matrix multiplication, are so slow that
  5700. the overhead of dealing with arrays in this fashion pales in comparison.
  5701. For other operations (e.g., extracting an element of an array), the overhead
  5702. required may far exceed the actual work performed.  This is why these routines
  5703. do provide access to the internal data structures.
  5704.  
  5705. The array access routines come in two basic groups: general array access and
  5706. array operations.  The general array access routines let you allocate arrays,
  5707. access arrays, initialize arrays, and copy arrays.  The array operation
  5708. routines let you perform high-level operations on the arrays.
  5709.  
  5710. SmartArrays are described by a descriptor (also called a "dope vector").  This
  5711. descriptor uses the following data structure:
  5712.  
  5713.     DopeVector    struc
  5714.     ArrayData    dd    ?
  5715.     SizeInBytes    dw    ?
  5716.     ElementSize    dw    ?
  5717.     NumDimensions    dw    ?
  5718.     DimensionList    dw    ?    ;One word for each dimension
  5719.     DopeVector    ends
  5720.  
  5721. The first double word is a pointer to the actual array data.  This is typically
  5722. (though not necessarily) allocated somewhere on the heap with malloc.  The
  5723. SmartArrays package stores all multi-dimensional arrays in row major order.
  5724.  
  5725. The second field above, SizeInBytes, gives the total size of the array data.
  5726. The SmartArray routines use this field for block copies and other operations
  5727. where it's nice to know the actual size of the array, in bytes.  Although
  5728. SmartArrays are typically allocated on the heap, there is no guarantee of this.
  5729. In particular, the SmartArray routines make no assumptions about free bytes
  5730. immediately following the array's data.  The SmartArray routines only
  5731. manipulate the specified number of bytes when treating the array as a whole.
  5732.  
  5733. The ElementSize field gives the number of bytes per array element.  Any value
  5734. may go here, but the SmartArrays package handles 1, 2, 4, 8, and 10 byte
  5735. elements best (especially 1, 2, and 4 byte element sizes).  Since most arrays
  5736. use one of these sizes, you're in great shape.
  5737.  
  5738. The NumDimensions field is an small integer which gives the number of dimen-
  5739. sions in this array.
  5740.  
  5741. The DimensionList is an array (despite its declaration) containing the number
  5742. of elements specified in the NumDimensions field.  Each entry is a word giving
  5743. the number of array elements in that dimension.
  5744.  
  5745.  
  5746.  
  5747. The SmartArrays package current defines the following error codes (which also
  5748. appear as equates in the stdlib.a files):
  5749.  
  5750. AryNoError    =    0            ;Should never occur
  5751. AryTypeMismatch    =    1            ;Array type mismatch
  5752. AryOverflow    =    2            ;Arithmetic overflow
  5753. AryDiv0        =    3            ;Division by zero
  5754. AryIllegalOp    =    4            ;Illegal operation on array
  5755. AryBounds    =    5            ;Array index error
  5756. AryMemory    =    6            ;Memory allocation error
  5757. AryBadDV    =    7            ;Illegal dope vector
  5758. AryNull        =    8            ;Null pointer to array data
  5759.  
  5760.  
  5761. If an error occurs, the SmartArray routines return with the carry set and
  5762. the error code in AX.  If no error occurs, then the SmartArray routines return
  5763. with the carry flag clear.  This is assuming that you have *not* defined the
  5764. "AryErrorAbort" symbol before the "include stdlib.a" statement in your program.
  5765. If you define the "AryErrorAbort" symbol before the include, the calls to the
  5766. SmartArray routines emit some additional code which checks for any errors.  If
  5767. an error occurs in this case, the system will print an appropriate error
  5768. message and abort the program.
  5769.  
  5770. In addition to the array dope vector structure, the stdlib.a files
  5771. also contain a macro for declaring SmartArrays within your program.  Although
  5772. it is perfectly possible to allocate dope vectors on the heap (and, indeed,
  5773. this is a common occurrence), more often than not it is possible to allocate
  5774. the dope vectors, and even the array data, in your data segment.  The
  5775. SmartArrays package provides a macro, "array", to specifically aid in this
  5776. task.  The array macro takes the following parameters:
  5777.  
  5778.     array    name, element_size, dimension_list, opt_initial_values
  5779.  
  5780. The name is the label you wish to attach to this smart array data structure.
  5781. This must be a valid assembly language symbol.  Note that the symbol must
  5782. *not* appear in the normal label field.  The macro does the processing of this
  5783. label and it must appear as a parameter to the macro.
  5784.  
  5785. The element_size parameter must be an integer value which is the number of
  5786. bytes to allocate for each array element.
  5787.  
  5788. The dimension_list parameter is a list of numbers, separated by commas and
  5789. surrounded by "<" and ">" which list the number of elements in each array
  5790. dimension.  This list must not be empty and none of the dimension values should
  5791. be zero.
  5792.  
  5793. The optional initial values is another list of values surrounded by "<" and
  5794. ">".  This parameter is optional and need not be present.  If absent, the
  5795. array macro generates a dope vector *only*.  It initializes the array data
  5796. pointer field to NULL.  If there are values present in the initial values
  5797. list, the array macro will allocate storage for the array immediately following
  5798. the dope vector and initializes the array elements to the value(s) in the
  5799. initial value list.  If there are too many items in the initial values list,
  5800. the array macro ignores the extra values.  If there are too few items, the
  5801. array macro reuses the values from the beginning of the list (over and over
  5802. again, if necessary).
  5803.  
  5804. Some examples (no initial values):
  5805.  
  5806.  
  5807. a1:array [0..1,0..1] of integer2;
  5808.  
  5809.     array    a1, 2, <2,2>
  5810.  
  5811.  
  5812. a2:array [0..7] of unsigned4;
  5813.  
  5814.     array    a2, 4, <8>
  5815.  
  5816. a3:array [0..3,0..3,0..3] of real8;
  5817.  
  5818.     array    a3, 8, <4,4,4>
  5819.  
  5820.  
  5821. Some examples with initial values:
  5822.  
  5823.     array    b1, 2, <4>, <1,2,3,4>
  5824.  
  5825.     array    b2, 2, <3>, <1,2,3,4>    ;ignores "4"
  5826.  
  5827.     array    b3, 2, <4>, <1,2,3>    ;Generates 1,2,3,1
  5828.  
  5829.     array    b4, 2, <4,4>, <1,0,0,0,0>
  5830.  
  5831. The last example generates the following identity matrix:
  5832.  
  5833.         1 0 0 0
  5834.         0 1 0 0
  5835.         0 0 1 0
  5836.         0 0 0 1
  5837.  
  5838. The array macro reuses initial values once it exhausts the list.  It also fills
  5839. the array in row-major order (that is, it fills up the array a row at a time).
  5840. Since each row in b4 is four bytes long and the initial values list contains
  5841. five bytes, the first pass through the initial values list creates the follow-
  5842. ing:
  5843.  
  5844.         1 0 0 0
  5845.         0 x x x
  5846.         x x x x
  5847.         x x x x
  5848.  
  5849. Since the initialization is not complete, the second pass through the initial
  5850. values list generates:
  5851.  
  5852.         1 0 0 0
  5853.         0 1 0 0
  5854.         0 0 x x
  5855.         x x x x
  5856.  
  5857. and so on.  It is important to note that the array macro ignores row/column
  5858. boundaries while initializing the array.  Array simply treats each array as
  5859. a one-dimensional object during initialization.
  5860.  
  5861. The array routines themselves come in three basic forms: general array manip-
  5862. ulation routines which operate on arrays of any size or dimension, vector
  5863. operations which operate only on single dimension arrays, and matrix operations
  5864. which operate on two-dimensional arrays.  General array operations typically
  5865. begin with the letters "Ary", vector operations usually begin with "vect", and
  5866. matrix routines usually begin with the letters "Mat".  All of these routines,
  5867. despite their name, belong to the SmartArrays package.
  5868.  
  5869.  
  5870.  
  5871. Interrupt-Driven Serial Port I/O Package
  5872. ========================================
  5873.  
  5874. One major problem the the PC's BIOS is the lack of good interrupt driven
  5875. I/O support for the serial port.  The BIOS provides a mediocre set of polled
  5876. I/O facilities, but completely drops the ball on interrupt driven I/O.
  5877.  
  5878. This set of routines in the standard library provides polled I/O support
  5879. to read and set the registers on the 8250 (or other comparable chip, e.g.,
  5880. 16450) as well as read and write data (polled).  In addition, there are
  5881. a pair of routines to initialize and disable the interrupt system as well
  5882. as perform I/O using interrupts.
  5883.  
  5884. Typical polled I/O session:
  5885.  
  5886. 1. Initialize chip using polled I/O routines.
  5887. 2. Read and write data using ComRead and ComWrite routines.
  5888.  
  5889. Typical interrupt driven I/O session:
  5890.  
  5891. 1. Initialize chip using polled I/O routines.
  5892. 2. Read and write data using ComIn and ComOut routines.
  5893.  
  5894. Of course, all the details of serial communications cannot be discussed
  5895. here- it's far too broad a subject.  These routines, like most in the
  5896. library, assume you know what you're doing.  They just make it a little
  5897. easier on you.  If you don't understand anything about serial communications,
  5898. you *might* be able to use these routines, but they were not written with
  5899. that audience in mind.  There are several good references on serial communi-
  5900. cations; "C Programmer's Guide to Serial Communications" comes to mind.  If
  5901. you've never looked at the 8250 or comparable chips before, you might want
  5902. to take a look at a reference such as this one if the routines in this
  5903. section don't make much sense.
  5904.  
  5905. Note: This routines are set up to use the COM1: hardware port.  See the
  5906. source listings if you want to access a different serial port.  Perhaps in
  5907. a future release we will modify this code to work with any serial port.
  5908.  
  5909.  
  5910. Routine:  ComBaud
  5911. -----------------
  5912.  
  5913. Author:                  Randall Hyde
  5914.  
  5915. Category:        Serial Communications
  5916.  
  5917. Registers on entry:       AX-    BPS (baud rate): 110, 150, 300, 600, 1200,
  5918.                          2400, 4800, 9600, 19200
  5919.  
  5920. Registers on return:      None
  5921.  
  5922. Flags affected:           None
  5923.  
  5924. Example of Usage:
  5925.             mov    ax, 9600    ;Set system to 9600 bps
  5926.             ComBaud
  5927. Description:
  5928.  
  5929. ComBaud programs the serial chip to change its "baud rate" (technically,
  5930. it's "bits per second" not baud rate).  You load AX with the appropriate
  5931. bps value and call ComBaud, as above.  Note: if AX is not one of the legal
  5932. values, ComBaud defaults to 19.2kbps.
  5933.  
  5934. Include:    ser.a or stdlib.a
  5935.  
  5936. Routine:  ComStop
  5937. -----------------
  5938.  
  5939. Author:                  Randall Hyde
  5940.  
  5941. Category:                 Serial Communications
  5942.  
  5943. Registers on entry:       AX-    # of stop bits (1 or 2)
  5944.  
  5945. Registers on return:      None
  5946.  
  5947. Flags affected:           None
  5948.  
  5949. Example of Usage:
  5950.             mov    ax, 2        ;Set system to send 2 stop bits
  5951.             ComStop
  5952. Description:
  5953.  
  5954. ComStop programs the serial chip to transmit the specifed number of stop
  5955. bits when sending data.  You load AX with the appropriate value and call
  5956. ComStop, as above.  Note that this only affects the output data stream. The
  5957. serial chip on the PC will always work with one incoming stop bit, regardless
  5958. of the setting.  Since additional stop bits slow down your data transmission
  5959. (by about 10%) and most devices work fine with one stop bit, you should
  5960. normally program the chip with one stop bit unless you encounter some
  5961. difficulties.  The setting of this value depends mostly on the system you
  5962. are connecting to.
  5963.  
  5964. Include:    ser.a or stdlib.a
  5965.  
  5966. Routine:  ComSize
  5967. -----------------
  5968.  
  5969. Author:                  Randall Hyde
  5970.  
  5971. Category:                 Serial Communications
  5972.  
  5973. Registers on entry:       AX-    # of data bits to transmit (5, 6, 7, or 8)
  5974.  
  5975. Registers on return:      None
  5976.  
  5977. Flags affected:           None
  5978.  
  5979. Example of Usage:
  5980.             mov    ax, 8    ;Set system to send 8 data bits
  5981.             ComSize
  5982. Description:
  5983.  
  5984. ComSize programs the serial chip to transmit the specifed number of data
  5985. bits when sending data.  You load AX with the appropriate value and call
  5986. ComSize, as above.  The setting of this value depends mostly on the system
  5987. you are connecting to.
  5988.  
  5989. Include:    ser.a or stdlib.a
  5990.  
  5991. Routine:  ComParity
  5992. -------------------
  5993.  
  5994. Author:                  Randall Hyde
  5995.  
  5996. Category:                 Serial Communications
  5997.  
  5998. Registers on entry:       AX-    Bits 0, 1, and 2 are defined as follows:
  5999.                    bit 0- 1 to enable parity, 0 to disable.
  6000.                    bit 1- 0 for odd parity, 1 for even.
  6001.                    bit 2- Stuck parity bit.  If 1 and bit 0 is 1, then the parity bit
  6002.                       is always set to the inverse of bit 1.
  6003.  
  6004. Registers on return:      None
  6005.  
  6006. Flags affected:           None
  6007.  
  6008. Example of Usage:
  6009.             mov    ax, 0    ;Set NO parity
  6010.             ComParity
  6011.              .
  6012.              .
  6013.              .
  6014.             mov    ax, 11b    ;Set even parity
  6015.             ComParity
  6016. Description:
  6017.  
  6018. ComParity programs the serial chip to use various forms of parity error
  6019. checking.  If bit zero of AX is zero, then this routine disables parity
  6020. checking and transmission.  In this case, ComParity ignores the other
  6021. two bits (actually, the 8250 ignores them, ComParity just passes them
  6022. through).  If bit zero is a one, and bit two is a zero, then bit #1
  6023. defines even/odd parity during transmission and receiving.  If bit #0
  6024. is a one and bit two is a one, then the 8250 will always transmit bit #1
  6025. as the parity bit (forced on or off).
  6026.  
  6027. Include:    ser.a or stdlib.a
  6028.  
  6029. Routine:  ComRead
  6030. -----------------
  6031.  
  6032. Author:                  Randall Hyde
  6033.  
  6034. Category:                 Serial Communications
  6035.  
  6036. Registers on entry:       None
  6037.  
  6038. Registers on return:      AL-    Character read from port
  6039.  
  6040. Flags affected:           None
  6041.  
  6042. Example of Usage:
  6043.             ComRead
  6044.             mov    Buffer, al
  6045.  
  6046. Description:
  6047.  
  6048. ComRead polls the port to see if a character is available in the on-chip
  6049. data register.  If not, it waits until a character is available.  Once
  6050. a character is available, ComRead reads it and returns this character in
  6051. the AL register.
  6052.  
  6053. Warning: do *not* use this routine while operating in the interrupt mode.
  6054. This routine is for polled I/O only.
  6055.  
  6056. Include:    ser.a or stdlib.a
  6057.  
  6058. Routine:  ComWrite
  6059. ------------------
  6060.  
  6061. Author:                  Randall Hyde
  6062.  
  6063. Category:                 Serial Communications
  6064.  
  6065. Registers on entry:       AL-    Character to write to port
  6066.  
  6067. Registers on return:      None
  6068.  
  6069. Flags affected:           None
  6070.  
  6071. Example of Usage:
  6072.             mov    al, 'a'
  6073.             ComWrite
  6074.  
  6075. Description:
  6076.  
  6077. ComWrite polls the port to see if the transmitter is busy.  If so, it waits
  6078. until the current transmission is through.  Once the 8250 is done with the
  6079. current character, ComWrite will put the character in AL into the 8250
  6080. transmit register.
  6081.  
  6082. Warning: do *not* use this routine while operating in the interrupt mode.
  6083. This routine is for polled I/O only.
  6084.  
  6085. Include:    ser.a or stdlib.a
  6086.  
  6087. Routine:  ComTstIn
  6088. ------------------
  6089.  
  6090. Author:                  Randall Hyde
  6091.  
  6092. Category:                 Serial Communications
  6093.  
  6094. Registers on entry:       None
  6095.  
  6096. Registers on return:      AL=0 if no char available, 1 if char available
  6097.  
  6098. Flags affected:           None
  6099.  
  6100. Example of Usage:
  6101.  
  6102.         Wait4Data:    ComTstIn
  6103.                 cmp    al, 0
  6104.                 je    Wait4Data
  6105.  
  6106. Description:
  6107.  
  6108. ComTstIn polls the port to see if any input data is available.  If so,
  6109. it returns a one in AL, else it returns a zero.
  6110.  
  6111. Warning: do *not* use this routine while operating in the interrupt mode.
  6112. This routine is for polled I/O only.
  6113.  
  6114. Include:    ser.a or stdlib.a
  6115.  
  6116. Routine:  ComTstOut
  6117. -------------------
  6118.  
  6119. Author:                  Randall Hyde
  6120.  
  6121. Category:                 Serial Communications
  6122.  
  6123. Registers on entry:       None
  6124.  
  6125. Registers on return:      AL = 1 if xmitr available, 0 if not
  6126.  
  6127. Flags affected:           None
  6128.  
  6129. Example of Usage:
  6130.  
  6131.         WriteData:    <Do Something>
  6132.                 ComTstOut
  6133.                 cmp    al, 0
  6134.                 je    WriteData
  6135.                 mov    al, 'a'
  6136.                 ComWrite
  6137.  
  6138. Description:
  6139.  
  6140. ComTstIn polls the port to see if the transmitter is currently busy.  If so,
  6141. it returns a zero in AL, else it returns a one.
  6142.  
  6143. Warning: do *not* use this routine while operating in the interrupt mode.
  6144. This routine is for polled I/O only.
  6145.  
  6146. Include:    ser.a or stdlib.a
  6147.  
  6148. Routine:  ComGetLSR
  6149. -------------------
  6150.  
  6151. Author:                  Randall Hyde
  6152.  
  6153. Category:                 Serial Communications
  6154.  
  6155. Registers on entry:       None
  6156.  
  6157. Registers on return:      AL = LSR value
  6158.  
  6159. Flags affected:           None
  6160.  
  6161. Example of Usage:
  6162.  
  6163.             ComGetLSR
  6164.             <do something with value in LSR>
  6165. Description:
  6166.  
  6167. Reads the LSR (line status register) and returns this value in AL.  The
  6168. LSR using the following layout.
  6169.  
  6170.  Line Status Register (LSR):
  6171.  
  6172.  bit 0-    Data Ready
  6173.  bit 1-    Overrun error
  6174.  bit 2-    Parity error
  6175.  bit 3-    Framing error
  6176.  bit 4-    Break Interrupt
  6177.  bit 5-    Transmitter holding register is empty.
  6178.  bit 6-    Transmit shift register is empty.
  6179.  bit 7-    Always zero.
  6180.  
  6181. Warning: In general, it is not a good idea to call this routine while
  6182. the interrupt system is active.  It won't hurt anything, but the value
  6183. you get back may not reflect properly upon the last/next character you
  6184. read.
  6185.  
  6186. Include:    ser.a or stdlib.a
  6187.  
  6188. Routine:  ComGetMSR
  6189. -------------------
  6190.  
  6191. Author:                  Randall Hyde
  6192.  
  6193. Category:                 Serial Communications
  6194.  
  6195. Registers on entry:       None
  6196.  
  6197. Registers on return:      AL = MSR value
  6198.  
  6199. Flags affected:           None
  6200.  
  6201. Example of Usage:
  6202.  
  6203.             ComGetMSR
  6204.             <do something with value in MSR>
  6205. Description:
  6206.  
  6207. The MSR (modem status register) bits are defined as follows:
  6208.  
  6209.  Modem Status Register (MSR):
  6210.  
  6211.  bit 0-    Delta CTS
  6212.  bit 1-    Delta DSR
  6213.  bit 2-    Trailing edge ring indicator
  6214.  bit 3-    Delta carrier detect
  6215.  bit 4-    Clear to send
  6216.  bit 5-    Data Set Ready
  6217.  bit 6-    Ring indicator
  6218.  bit 7-    Data carrier detect
  6219.  
  6220.  
  6221. Warning: In general, it is not a good idea to call this routine while
  6222. the interrupt system is active.  It won't hurt anything, but the value
  6223. you get back may not reflect properly upon the last/next character you
  6224. read.
  6225.  
  6226. Include:    ser.a or stdlib.a
  6227.  
  6228. Routine:  ComGetMCR
  6229. -------------------
  6230.  
  6231. Author:                  Randall Hyde
  6232.  
  6233. Category:                 Serial Communications
  6234.  
  6235. Registers on entry:       None
  6236.  
  6237. Registers on return:      AL = MCR value
  6238.  
  6239. Flags affected:           None
  6240.  
  6241. Example of Usage:
  6242.  
  6243.             ComGetMCR
  6244.             <do something with value in MCR>
  6245. Description:
  6246.  
  6247. The MCR (modem control register) bits are defined as follows:
  6248.  
  6249.  Modem Control Register (MCR):
  6250.  
  6251.  bit 0-        Data Terminal Ready (DTR)
  6252.  bit 1-        Request to send (RTS)
  6253.  bit 2-        OUT 1
  6254.  bit 3-        OUT 2
  6255.  bit 4-        Loop back control.
  6256.  bits 5-7-    Always zero.
  6257.  
  6258.  
  6259. The DTR and RTS bits control the function of these lines on the 8250.
  6260. They are useful mainly for polled I/O handshake operations (though they
  6261. *could* be used with interrupt I/O, it's rarely necessary unless your
  6262. main application is *really* slow and the data is coming in real fast.
  6263.  
  6264. Out1 and Out2 control output pins on the 8255.  Keep in mind that the OUT1
  6265. pin enables/disables the serial port interrupts.  Play with this *only* if
  6266. you want to control the interrupt enable.
  6267.  
  6268. Loop back control is mainly useful for testing the serial port or checking
  6269. to see if a serial chip is present.
  6270.  
  6271. Include:    ser.a or stdlib.a
  6272.  
  6273. Routine:  ComSetMCR
  6274. -------------------
  6275.  
  6276. Author:                  Randall Hyde
  6277.  
  6278. Category:                 Serial Communications
  6279.  
  6280. Registers on entry:       AL = new MCR value
  6281.  
  6282. Registers on return:      None
  6283.  
  6284. Flags affected:           None
  6285.  
  6286. Example of Usage:
  6287.  
  6288.             mov    al, NewMCRValue
  6289.             ComSetMCR
  6290.  
  6291. Description:
  6292.  
  6293. This routine writes the value in AL to the modem control register.  See
  6294. ComGetMCR for details on the MCR register.
  6295.  
  6296. Include:    ser.a or stdlib.a
  6297.  
  6298. Routine:  ComGetLCR
  6299. -------------------
  6300.  
  6301. Author:                  Randall Hyde
  6302.  
  6303. Category:                 Serial Communications
  6304.  
  6305. Registers on entry:       None
  6306.  
  6307. Registers on return:      AL = LCR value
  6308.  
  6309. Flags affected:           None
  6310.  
  6311. Example of Usage:
  6312.  
  6313.             ComGetLCR
  6314.             <do something with value in LCR>
  6315. Description:
  6316.  
  6317. The LCR (line control register) bits are defined as follows:
  6318.  
  6319.  Line Control Register (LCR):
  6320.  
  6321.  bits 0,1-    Word length (00=5, 01=6, 10=7, 11=8 bits).
  6322.  bit 2-        Stop bits (0=1, 1=2 stop bits [1-1/2 if 5 data bits]).
  6323.  bit 3-        Parity enabled if one.
  6324.  bit 4-        0 for odd parity, 1 for even parity (assuming bit 3 = 1).
  6325.  bit 5-        1 for stuck parity.
  6326.  bit 6-        1=force break.
  6327.  bit 7-        1=Divisor latch access bit.  0=rcv/xmit access bit.
  6328.  
  6329. Since the standard library provides routines to initialize the serial chip
  6330. (which is the purpose of this port) you shouldn't really mess with this
  6331. port at all.  You may, however, use ComGetLCR to see what the current
  6332. settings are before making any changes.
  6333.  
  6334. Warning: (applies mainly to ComSetLCR) DO NOT, UNDER ANY CIRCUMSTANCES,
  6335. CHANGE THE DIVISOR LATCH ACCESS BIT WHILE OPERATING IN INTERRUPT MODE.
  6336. The interrupt service routine assumes the rcv/xmit register is mapped in
  6337. whenever an interrupt occurs.  If you must play with the divisor latch,
  6338. turn off interrupts before changing it.  Always set the divisor latch
  6339. access bit back to zero before turning interrupts back on.
  6340.  
  6341. Include:    ser.a or stdlib.a
  6342.  
  6343. Routine:  ComSetLCR
  6344. -------------------
  6345.  
  6346. Author:                  Randall Hyde
  6347.  
  6348. Category:                 Serial Communications
  6349.  
  6350. Registers on entry:       AL = new LCR value
  6351.  
  6352. Registers on return:      None
  6353.  
  6354. Flags affected:           None
  6355.  
  6356. Example of Usage:
  6357.  
  6358. ; If this maps in the divisor latch, be sure we're not operating with
  6359. ; serial interrupts!
  6360.  
  6361.             mov    al, NewLCRValue
  6362.             ComSetLCR
  6363.  
  6364. Description:
  6365.  
  6366. This routine writes the value in AL to the line control register.  See
  6367. ComGetLCR for details on the LCR register.  Especially note the warning
  6368. about the divisor latch access bit.
  6369.  
  6370. Include:    ser.a or stdlib.a
  6371.  
  6372. Routine:  ComGetIIR
  6373. -------------------
  6374.  
  6375. Author:                  Randall Hyde
  6376.  
  6377. Category:                 Serial Communications
  6378.  
  6379. Registers on entry:       None
  6380.  
  6381. Registers on return:      AL = IIR value
  6382.  
  6383. Flags affected:           None
  6384.  
  6385. Example of Usage:
  6386.  
  6387.             ComGetIIR
  6388.             <do something with value in IIR>
  6389. Description:
  6390.  
  6391. The IIR (interrupt identification register) bits are defined as follows:
  6392.  
  6393.  Interrupt ID Register (IIR):
  6394.  
  6395.  bit 0-        No interrupt is pending (interrupt pending if zero).
  6396.  bits 1,2-    Binary value denoting source of interrupt:
  6397.             00-Modem status
  6398.             01-Transmitter Hold Register Empty
  6399.             10-Received Data Available
  6400.             11-Receiver line status
  6401.  bits 3-7    Always zero.
  6402.  
  6403. This value is of little use to anyone except the interrupt service routine.
  6404. The ISR is the only code which should really access this port.
  6405.  
  6406. Include:    ser.a or stdlib.a
  6407.  
  6408. Routine:  ComGetIER
  6409. -------------------
  6410.  
  6411. Author:                  Randall Hyde
  6412.  
  6413. Category:                 Serial Communications
  6414.  
  6415. Registers on entry:       None
  6416.  
  6417. Registers on return:      AL = IER value
  6418.  
  6419. Flags affected:           None
  6420.  
  6421. Example of Usage:
  6422.  
  6423.             ComGetIER
  6424.             <do something with value in IER>
  6425. Description:
  6426.  
  6427. The IER (line control register) bits are defined as follows:
  6428.  
  6429.  Interupt enable register (IER):
  6430.  
  6431.         If one:
  6432.  bit 0-        Enables received data available interrupt.
  6433.  bit 1-        Enables transmitter holding register empty interrupt.
  6434.  bit 2-        Enables receiver line status interrupt.
  6435.  bit 3-        Enables the modem status interrupt.
  6436.  bits 4-7-    Always set to zero.
  6437.  
  6438. Normally, the interrupt initialization procedure sets up this port.  You may
  6439. read or change its value as you deem necessary to control the types of
  6440. interrupts the system generates.  Note that the interrupt service routine
  6441. (ISR) in the library ignores errors.  You will need to modify the ISR if you
  6442. need to trap errors.
  6443.  
  6444. Include:    ser.a or stdlib.a
  6445.  
  6446. Routine:  ComSetIER
  6447. -------------------
  6448.  
  6449. Author:                  Randall Hyde
  6450.  
  6451. Category:                 Serial Communications
  6452.  
  6453. Registers on entry:       AL = new IER value
  6454.  
  6455. Registers on return:      None
  6456.  
  6457. Flags affected:           None
  6458.  
  6459. Example of Usage:
  6460.  
  6461.             mov    al, NewIERValue
  6462.             ComSetIER
  6463.  
  6464. Description:
  6465.  
  6466. Writes the value in AL to the IER.  See ComGetIER for more details.
  6467.  
  6468. Include:    ser.a or stdlib.a
  6469.  
  6470. Routine:  ComInitIntr
  6471. ---------------------
  6472.  
  6473. Author:                  Randall Hyde
  6474.  
  6475. Category:                 Serial Communications
  6476.  
  6477. Registers on entry:       None
  6478.  
  6479. Registers on return:      None
  6480.  
  6481. Flags affected:           None
  6482.  
  6483. Example of Usage:
  6484.  
  6485.             ComInitIntr
  6486.  
  6487. Description:
  6488.  
  6489. Sets up the chip to generate interrupts and programs the PC to transfer
  6490. control to the library serial interrupt service routine when an interrupt
  6491. occurs.  Note that other than interrupt initialization, this code does not
  6492. initialize the 8250 chip.
  6493.  
  6494. Include:    ser.a or stdlib.a
  6495.  
  6496. Routine:  ComDisIntr
  6497. --------------------
  6498.  
  6499. Author:                  Randall Hyde
  6500.  
  6501. Category:                 Serial Communications
  6502.  
  6503. Registers on entry:       None
  6504.  
  6505. Registers on return:      None
  6506.  
  6507. Flags affected:           None
  6508.  
  6509. Example of Usage:
  6510.  
  6511.             ComDisIntr
  6512.  
  6513. Description:
  6514.  
  6515. This routine uninstalls the ISR and programs the chip to stop the generation
  6516. of interrupts.  You must call ComInitIntr after calling this routine to
  6517. turn the interrupt system back on.
  6518.  
  6519. Include:    ser.a or stdlib.a
  6520.  
  6521. Routine:  ComIn
  6522. ---------------
  6523.  
  6524. Author:                  Randall Hyde
  6525.  
  6526. Category:                 Serial Communications
  6527.  
  6528. Registers on entry:       None
  6529.  
  6530. Registers on return:      AL=character read from buffer or port
  6531.  
  6532. Flags affected:           None
  6533.  
  6534. Example of Usage:
  6535.  
  6536.             ComIn
  6537.             <Do something with AL>
  6538.  
  6539. Description:
  6540.  
  6541. ComIn is the input routine associated with interrupt I/O.  It reads the
  6542. next available character from the serial input buffer.  If no characters
  6543. are avialable in the buffer, it waits until the system receives one before
  6544. returning.
  6545.  
  6546. Include:    ser.a or stdlib.a
  6547.  
  6548. Routine:  ComOut
  6549. ----------------
  6550.  
  6551. Author:                  Randall Hyde
  6552.  
  6553. Category:                 Serial Communications
  6554.  
  6555. Registers on entry:       AL=Character to output
  6556.  
  6557. Registers on return:      None
  6558.  
  6559. Flags affected:           None
  6560.  
  6561. Example of Usage:
  6562.  
  6563.             <Get character to write into AL>
  6564.             ComOut
  6565.  
  6566. Description:
  6567.  
  6568. ComOut is the output routine associated with interrupt I/O.  If the serial
  6569. transmitter isn't currently busy, it will immediately write the data to the
  6570. serial port.  If it is busy, it will buffer the character up.  In most cases
  6571. this routine returns quickly to its caller.  The only time this routine
  6572. will delay is if the buffer is full can you cannot add any additional
  6573. characters to it.
  6574.  
  6575. Include:    ser.a or stdlib.a
  6576.  
  6577. Linked list manipulation routines
  6578. =================================
  6579.  
  6580. These routines manipulate items in a linked list.  Internally the system
  6581. represents the data as a doubly linked list, although your program should
  6582. not rely on the internal structure of the data structure.
  6583.  
  6584. There are two structures of interest defined in the LISTS.A file: LIST
  6585. and NODE.  Use variables of type LIST to create brand new lists.  Use
  6586. variables of type NODE to hold the entries in the list.
  6587.  
  6588. These structures take the following form:
  6589.  
  6590. List        struc
  6591. Size        dw    ?        ;Size, in bytes, of a node in the list
  6592. Head        dd    0        ;Ptr to start of list
  6593. Tail        dd    0        ;Ptr to end of list
  6594. Current        dd    0        ;Pointer to current node
  6595. List        ends
  6596.  
  6597. Node        struc
  6598. Next        dd    ?        ;Ptr to next node in list
  6599. Prev        dd    ?        ;Ptr to prev node in list
  6600. NodeData    db    ??        ;Data immediately follows Prev
  6601. Node        ends
  6602.  
  6603.  
  6604. There are two ways to create a new list: statically or dynamically.
  6605. Consider static allocation first.  In this case, you create a list variable
  6606. by declaring an object of type LIST in a data segment, e.g.,
  6607.  
  6608. MyList        list    <25>
  6609.  
  6610. You *must* supply the size (in bytes) of a node in the list.  Note that the
  6611. size should *not* include the eight bytes required for the next and prev
  6612. pointers.  This allows you to change the internal structure of the list
  6613. (e.g., to a singly linked list) without having to change other code.  You
  6614. can easily compute this as follows:
  6615.  
  6616. MyList        list    <(sizeof MyNode) - (sizeof Node)>
  6617.  
  6618. When you declare lists in this fashion, the definition automatically
  6619. initializes the list to an empty list.
  6620.  
  6621. You can also create a list dynamically by calling the CreateList routine.
  6622. To CreateList you must pass the size of a Node (not including the pointers)
  6623. in the CX register.  It allocates storage for the list variable on the
  6624. heap and returns a pointer to this new (empty) list in es:di.
  6625.  
  6626.         mov    cx, (sizeof MyNode) - (sizeof Node)
  6627.         CreateList
  6628.         mov    word ptr MyListPtr, di
  6629.         mov    word ptr MyListPtr+2, es
  6630.  
  6631.  
  6632. To create nodes for your list, you should "overload" the NODE definition
  6633. appearing the in LISTS.A file.  This works best under MASM 6.0 and TASM 3.0,
  6634. which support object-oriented programming, though it isn't that difficult to
  6635. accomplish with other assemblers.  A mechanism compatible with *all*
  6636. assemblers follows:
  6637.  
  6638. To create a brand new node is easy,  just do the following:
  6639.  
  6640. MyNode        struc
  6641.         db    (size Node) dup (0)     ;Inherit all fields from NODE.
  6642. Field1        db    ?            ;User-supplied fields for this
  6643. Field2        dw    ?            ; particular node type.
  6644. Field3        dd    ?            ;  "    "     "    "
  6645. Field4        real4    3.14159            ;  "    "     "    "
  6646. MyNode        ends
  6647.  
  6648. Note that the NODE fields must appear *first* in the data structure.
  6649. The list manipulation routines assume that the list pointers in NODE appear
  6650. at the beginning of the structure.
  6651.  
  6652. The CurrentNode field of the list data structure points at a "current" node
  6653. in the list.  The current node is the last node operated on in the case of
  6654. insert, append, peek, etc.  In the event a node is removed, the current node
  6655. will be the next node after the node removed.  In general, the current node
  6656. can be thought of as a "cursor" which wanders through the list according to
  6657. the operations occuring.  Since most list operations occur on the next node
  6658. in a list, keeping the CurrentNode field updated speeds up access to the
  6659. list.
  6660.  
  6661. You can use the following routines to implement the corresponding data
  6662. structures (which can all be implemented using lists):
  6663.  
  6664. FIFO Queues:
  6665.  
  6666. AppendLastm, AppendLast, Remove1st, and Peek1st (technically, using Peek1st
  6667. is cheating, but so what).
  6668.  
  6669.  
  6670.  
  6671. Deques (double ended queues):
  6672.  
  6673. All the FIFO routines plus InsertFirstm, InsertFirst, RemoveLast, and
  6674. PeekLast (PeekLast is cheating too).
  6675.  
  6676.  
  6677. Lists:
  6678.  
  6679. All of the above plus InsertCur, InsertmCur, AppendCur, AppendmCur,
  6680. RemoveCur, Insert, Insertm, Append, Appendm, Remove, Index, RotateLeft,
  6681. RotateRight, NextNode, and PrevNode.
  6682.  
  6683. For those who care about such things, the UCR Standard Library implements
  6684. the list data structure using a doubly linked list.  However, it is a
  6685. true generic (encapsulated) data type and your code needed be at all
  6686. concerned about the internal structure.  Furthermore, assuming you treat
  6687. it like an encapsulated data structure, you can modify the internal list
  6688. structure and not break any programs which use the list data types.
  6689.  
  6690.  
  6691.  
  6692.  
  6693.  
  6694. Routine:  CreateList
  6695. --------------------
  6696.  
  6697. Author:              Randall Hyde
  6698.  
  6699. Category:             List Manipulation
  6700.  
  6701. Registers on entry:       CX-    Size of data (in bytes) to store at each node
  6702.  
  6703. Registers on return:      ES:DI-    Pointer to new list variable on heap
  6704.  
  6705. Flags affected:           Carry set if CreateList cannot allocate sufficient
  6706.             storage on the heap for the list variable.
  6707.  
  6708. Example of Usage:
  6709.             mov    cx, (sizeof MyNode) - (sizeof Node)
  6710.             CreateList
  6711.             jc    ListError
  6712.             mov    word ptr ListVarPtr, di
  6713.             mov    word ptr ListVarPtr+2, es
  6714.  
  6715. Description:
  6716.  
  6717. CreateList allocates storage for a list variable on the head and initializes
  6718. that variable to the empty list.  It also sets up the size field of the
  6719. list variable based on the value passed in the CX register.  It returns
  6720. a pointer to the newly created list in the ES:DI registers.
  6721.  
  6722. This routine initializes the CurrentNode field to NIL.  Any node inserted
  6723. before or after the current node will be inserted as the first node in this
  6724. case.
  6725.  
  6726. Include:    lists.a or stdlib.a
  6727.  
  6728.  
  6729.  
  6730. Routine:  AppendLast (m)
  6731. ------------------------
  6732.  
  6733. Author:              Randall Hyde
  6734.  
  6735. Category:             List Manipulation
  6736.  
  6737. Registers on entry:       DX:SI-    Pointer to node to add to list (AppendLast)
  6738.             DX:SI-    Pointer to block of data (sans list stuff)
  6739.                 to add to end of list (AppendLastm)
  6740.             ES:DI-    Pointer to list.
  6741.  
  6742. Registers on return:      ES:DI-    Pointer to list.
  6743.  
  6744. Flags affected:           Carry set if AppendLastm cannot allocate sufficient
  6745.             storage on the heap for the list variable.
  6746.  
  6747. Examples of Usage:
  6748.  
  6749. ; Append data statically declared as ANode to the end of the list pointed at
  6750. ; by the list variable "ListVar".
  6751.  
  6752.             ldxi    ANode
  6753.             les    di, ListVar
  6754.             AppendLast
  6755.  
  6756. ; Create a node from the data at address "MyData".  Build the node on the
  6757. ; heap and append this node to the end of the list pointed at by ListVar.
  6758.  
  6759.             ldxi    MyData
  6760.             les    di, ListVar
  6761.             AppendLastm
  6762.             jc    BadListError
  6763.  
  6764. Description:
  6765.  
  6766. AppendLast and AppendLastm add a node to the end of a list.  AppendLast works
  6767. with whole nodes.  It is useful, for example when moving a node from one
  6768. list to another or when dealing with nodes that were created statically in
  6769. the program.  It requires nodes properly declared using the NODE data type
  6770. in the LIST.A include file.
  6771.  
  6772. AppendLastm builds a new node on the heap and appends this node to the end
  6773. of the specified list.  The difference between AppendLastm and AppendLast is
  6774. that AppendLastm does not require a predefined node.  Instead, DX:SI points
  6775. at the data for the node (the number of bytes is specified by the ListSize
  6776. field of the LIST data type).  AppendLastm allocates memory, copies the data
  6777. from DX:SI to the data field of the new node, and then links in the new node
  6778. to the specified list.
  6779.  
  6780. The new node added to the list becomes the CurrentNode.
  6781.  
  6782. Include:    stdlib.a or lists.a
  6783.  
  6784.  
  6785.  
  6786. Routine:  Remove1st
  6787. -------------------
  6788.  
  6789. Author:                  Randall Hyde
  6790.  
  6791. Category:                 List Manipulation
  6792.  
  6793. Registers on entry:       ES:DI-    Pointer to list variable.
  6794.  
  6795. Registers on return:    DX:SI-    Pointer to node removed from the front of
  6796.                 the list (NIL if nothing in list).
  6797.  
  6798. Flags affected:           Carry set if the list was empty.
  6799.  
  6800. Examples of Usage:
  6801.  
  6802. ; The following loop removes all the items from a list and processes each
  6803. ; item.
  6804.  
  6805. DoAllOfList:        les    di, MyList
  6806.             Remove1st
  6807.             jc    DidItAll
  6808.             <manipulate this item>
  6809.             jmp    DoAllOfList
  6810. DidItAll:
  6811.  
  6812.  
  6813. Description:
  6814.  
  6815. Remove1st removes the first item from a list and returns a pointer to that
  6816. item in DX:SI.  If the list was empty, then it returns a NIL pointer in
  6817. DX:SI and returns with the carry flag set.
  6818.  
  6819. Note that you can use the AppendLast(m) and Remove1st routines to implement
  6820. and manipulate a FIFO queue data structure.  Peek1st is another useful
  6821. routine which returns the first item on a list without removing it from
  6822. the list.
  6823.  
  6824. The second node in the list (the one after the node just removed) becomes
  6825. the new CurrentNode.  If there are no additional nodes in the list, the
  6826. CurrentNode variable gets set to NIL.
  6827.  
  6828. Include:    stdlib.a or lists.a
  6829.  
  6830.  
  6831.  
  6832.  
  6833. Routine:  Peek1st
  6834. -----------------
  6835.  
  6836. Author:                  Randall Hyde
  6837.  
  6838. Category:                 List Manipulation
  6839.  
  6840. Registers on entry:       ES:DI-    Pointer to list variable.
  6841.  
  6842. Registers on return:    DX:SI-    Pointer to node at the beginning of
  6843.                 the list (NIL if nothing in list).
  6844.  
  6845. Flags affected:           Carry set if the list was empty.
  6846.  
  6847. Examples of Usage:
  6848.  
  6849.             les    di, MyList
  6850.             Peek1st
  6851.             jc    NothingThere
  6852.  
  6853. Description:
  6854.  
  6855. Peek1st is similar to Remove1st in that it returns a pointer to the first
  6856. item in a list (NIL if the list is empty).  However, it does not remove the
  6857. item from the list.  This is useful for performing a "non-destructive" read
  6858. of the first item in a FIFO queue.
  6859.  
  6860. This routine sets the CurrentNode field to the first node in the list.
  6861.  
  6862. Include:    stdlib.a or lists.a
  6863.  
  6864.  
  6865.  
  6866. Routine:  Insert1st (m)
  6867. -----------------------
  6868.  
  6869. Author:              Randall Hyde
  6870.  
  6871. Category:             List Manipulation
  6872.  
  6873. Registers on entry:       DX:SI-    Pointer to node to add to list (Insert1st)
  6874.             DX:SI-    Pointer to block of data (sans list stuff)
  6875.                 to add to end of list (Insert1stm)
  6876.             ES:DI-    Pointer to list.
  6877.  
  6878. Registers on return:      ES:DI-    Pointer to list.
  6879.  
  6880. Flags affected:           Carry set if Insertm cannot allocate sufficient
  6881.             storage on the heap for the list variable.
  6882.  
  6883. Examples of Usage:
  6884.  
  6885. ; Insert data statically declared as ANode to the beginning of the list
  6886. ; pointed at by the list variable "ListVar".
  6887.  
  6888.             ldxi    ANode
  6889.             les    di, ListVar
  6890.             Insert1st
  6891.  
  6892. ; Create a node from the data at address "MyData".  Build the node on the
  6893. ; heap and insert this node to the beginning of the list pointed at by
  6894. ; ListVar.
  6895.  
  6896.             ldxi    MyData
  6897.             les    di, ListVar
  6898.             Insert1stm
  6899.             jc    BadListError
  6900.  
  6901. Description:
  6902.  
  6903. Insert1st and Insert1stm add a node to the beginning of a list.  Insert1st
  6904. works with whole nodes.  It is useful, for example when moving a node from one
  6905. list to another or when dealing with nodes that were created statically in
  6906. the program.  It requires nodes properly declared using the NODE data type
  6907. in the LISTS.A include file.
  6908.  
  6909. Insert1stm builds a new node on the heap and inserts this node to the start
  6910. of the specified list.  The difference between Insert1stm and Insert1st is
  6911. that Insert1stm does not require a predefined node.  Instead, DX:SI points
  6912. at the data for the node (the number of bytes is specified by the ListSize
  6913. field of the LIST data type).  Insert1stm allocates memory, copies the data
  6914. from DX:SI to the data field of the new node, and then links in the new node
  6915. to the specified list.
  6916.  
  6917. Note that Insert1st/Insert1stm can be used to create Deque data structures.
  6918.  
  6919. The newly inserted node becomes the CurrentNode in the list.
  6920.  
  6921. Include:    stdlib.a or lists.a
  6922.  
  6923.  
  6924.  
  6925. Routine:  RemoveLast
  6926. --------------------
  6927.  
  6928. Author:                  Randall Hyde
  6929.  
  6930. Category:                 List Manipulation
  6931.  
  6932. Registers on entry:       ES:DI-    Pointer to list variable.
  6933.  
  6934. Registers on return:    DX:SI-    Pointer to node removed from the end of
  6935.                 the list (NIL if nothing in list).
  6936.  
  6937. Flags affected:           Carry set if the list was empty.
  6938.  
  6939. Examples of Usage:
  6940.  
  6941. ; The following loop removes all the items from a list and processes each
  6942. ; item.
  6943.  
  6944. DoAllOfList:        les    di, MyList
  6945.             RemoveLast
  6946.             jc    DidItAll
  6947.             <manipulate this item>
  6948.             jmp    DoAllOfList
  6949. DidItAll:
  6950.  
  6951.  
  6952. Description:
  6953.  
  6954. RemoveLast removes the last item from a list and returns a pointer to that
  6955. item in DX:SI.  If the list was empty, then it returns a NIL pointer in
  6956. DX:SI and returns with the carry flag set.
  6957.  
  6958. Note that you can use the Insert1st(m) and RemoveLast routines to implement
  6959. and manipulate a DEQUE queue data structure (along with the FIFO routines:
  6960. AppendLast(m), Rmv1st, and Peek1st).  PeekLast is another useful
  6961. routine which returns the last item on a list without removing it from
  6962. the list.
  6963.  
  6964. The last node in the list (the one before the node just removed) becomes the
  6965. new CurrentNode in the list.  If the list is empty, CurrentNode gets set to
  6966. NIL.
  6967.  
  6968. Include:    stdlib.a or lists.a
  6969.  
  6970.  
  6971.  
  6972.  
  6973. Routine:  PeekLast
  6974. ------------------
  6975.  
  6976. Author:                  Randall Hyde
  6977.  
  6978. Category:                 List Manipulation
  6979.  
  6980. Registers on entry:       ES:DI-    Pointer to list variable.
  6981.  
  6982. Registers on return:    DX:SI-    Pointer to node at the end of
  6983.                 the list (NIL if nothing in list).
  6984.  
  6985. Flags affected:           Carry set if the list was empty.
  6986.  
  6987. Examples of Usage:
  6988.  
  6989.             les    di, MyList
  6990.             PeekLast
  6991.             jc    NothingThere
  6992.  
  6993. Description:
  6994.  
  6995. PeekLast is just like Peek1st except it looks at the last node on the list
  6996. rather than the first.  It does the same job as RemoveLast except it does
  6997. not remove the node from the list.  Great for implementing Deques.
  6998.  
  6999. This routine also sets the CurrentNode field to point at the last node in
  7000. the list.
  7001.  
  7002. Include:    stdlib.a or lists.a
  7003.  
  7004.  
  7005.  
  7006.  
  7007. Routine:  InsertCur
  7008. -------------------
  7009.  
  7010. Author:                  Randall Hyde
  7011.  
  7012. Category:                 List Manipulation
  7013.  
  7014. Registers on entry:       ES:DI-    Pointer to list.
  7015.             DX:SI-    Pointer to node to insert
  7016.  
  7017. Examples of Usage:
  7018.  
  7019.             les    di, MyList
  7020.             ldxi    NewNode
  7021.             InsertCur
  7022.  
  7023. Description:
  7024.  
  7025. InsertCur inserts the node pointed at by DX:SI before the "current" node in
  7026. the list.  The current node is the last one operated on by the software.
  7027.  
  7028. The newly inserted node becomes the CurrentNode in the list.
  7029.  
  7030. Include:    stdlib.a or lists.a
  7031.  
  7032.  
  7033.  
  7034.  
  7035. Routine:  InsertmCur
  7036. --------------------
  7037.  
  7038. Author:                  Randall Hyde
  7039.  
  7040. Category:                 List Manipulation
  7041.  
  7042. Registers on entry:       ES:DI-    Pointer to list.
  7043.             DX:SI-    Pointer to data for node to insert
  7044.  
  7045. Flags on exit:        Carry flag is set if malloc error occurs.
  7046.  
  7047. Examples of Usage:
  7048.  
  7049.             les    di, MyList
  7050.             ldxi    DataBlock
  7051.             InsertmCur
  7052.             jc    Error
  7053.  
  7054. Description:
  7055.  
  7056. InsertmCur builds a new node on the heap (using the block of data pointed at
  7057. by DX:SI and the size of a node in the size field of the list variable) and
  7058. then inserts the new node before the "current" node in the list.  The current
  7059. node is the last one operated on by the software.
  7060.  
  7061. This code treats the newly inserted node as the current node.
  7062.  
  7063. Include:    stdlib.a or lists.a
  7064.  
  7065.  
  7066.  
  7067. Routine:  AppendCur
  7068. -------------------
  7069.  
  7070. Author:                  Randall Hyde
  7071.  
  7072. Category:                 List Manipulation
  7073.  
  7074. Registers on entry:       ES:DI-    Pointer to list.
  7075.             DX:SI-    Pointer to node to append
  7076.  
  7077. Examples of Usage:
  7078.  
  7079.             les    di, MyList
  7080.             ldxi    NewNode
  7081.             AppendCur
  7082.  
  7083. Description:
  7084.  
  7085. AppendCur inserts the node pointed at by DX:SI after the "current" node in
  7086. the list.  The current node is the last one operated on by the software.
  7087.  
  7088. The newly inserted node becomes the CurrentNode in the list.
  7089.  
  7090. Include:    stdlib.a or lists.a
  7091.  
  7092.  
  7093.  
  7094.  
  7095. Routine:  AppendmCur
  7096. --------------------
  7097.  
  7098. Author:                  Randall Hyde
  7099.  
  7100. Category:                 List Manipulation
  7101.  
  7102. Registers on entry:       ES:DI-    Pointer to list.
  7103.             DX:SI-    Pointer to data for node to insert.
  7104.  
  7105. Flags on exit:        Carry flag is set if malloc error occurs.
  7106.  
  7107. Examples of Usage:
  7108.  
  7109.             les    di, MyList
  7110.             ldxi    DataBlock
  7111.             AppendmCur
  7112.             jc    MallocError
  7113.  
  7114. Description:
  7115.  
  7116. AppendmCur builds a new node on the heap (using the block of data pointed at
  7117. by DX:SI and the size of a node in the size field of the list variable) and
  7118. then inserts the new node after the "current" node in the list.  The current
  7119. node is the last one operated on by the software.
  7120.  
  7121. This code treats the newly inserted node as the current node.
  7122.  
  7123. Include:    stdlib.a or lists.a
  7124.  
  7125.  
  7126.  
  7127. Routine:  RemoveCur
  7128. -------------------
  7129.  
  7130. Author:                  Randall Hyde
  7131.  
  7132. Category:                 List Manipulation
  7133.  
  7134. Registers on entry:       ES:DI-    Pointer to list.
  7135.  
  7136. Registers on exit:    DX:SI-    Points at node removed from list (NIL if
  7137.                 no such node).
  7138.  
  7139. Flags on return:    Carry set if the list was empty.
  7140.  
  7141. Examples of Usage:
  7142.  
  7143.             les    di, MyList
  7144.             RemoveCur
  7145.             jc    EmptyList
  7146.  
  7147. Description:
  7148.  
  7149. RemoveCur removes the current node (pointed at by CurrentNode) from the list
  7150. and returns a pointer to this node in DX:SI.  If the list was empty, RemoveCur
  7151. returns NIL in DX:SI and sets the carry flag.
  7152.  
  7153. This routine modifies CurrentNode so that it points at the next item in the
  7154. list (the node normally following the current node).  If there is no such
  7155. node (i.e., CurrentNode pointed at the last node in the list upon calling
  7156. RemoveCur) then this routine stores the value of the *previous* node into
  7157. CurrentNode.  If you use this routine to delete the last node in the list,
  7158. it sets CurrentNode to NIL before leaving.
  7159.  
  7160. Include:    stdlib.a or lists.a
  7161.  
  7162.  
  7163.  
  7164. Routine:  PeekCur
  7165. -----------------
  7166.  
  7167. Author:                  Randall Hyde
  7168.  
  7169. Category:                 List Manipulation
  7170.  
  7171. Registers on entry:       ES:DI-    Pointer to list.
  7172.  
  7173. Registers on exit:    DX:SI-    Points at the current node (i.e., contains
  7174.                 a copy of CurrentNode), NIL if the list
  7175.                 is empty.
  7176.  
  7177. Flags on return:    Carry set if the list was empty.
  7178.  
  7179. Examples of Usage:
  7180.  
  7181.             les    di, MyList
  7182.             PeekCur
  7183.             jc    EmptyList
  7184.  
  7185. Description:
  7186.  
  7187. PeekCur simply returns CurrentNode in DX:SI (assuming the list is not empty).
  7188. If the list is empty, it returns the carry flag set and NIL in DX:SI.
  7189. It does not affect the value of CurrentNode.
  7190.  
  7191. Include:    stdlib.a or lists.a
  7192.  
  7193.  
  7194.  
  7195. Routine:  SetCur
  7196. ----------------
  7197.  
  7198. Author:                  Randall Hyde
  7199.  
  7200. Category:                 List Manipulation
  7201.  
  7202. Registers on entry:       ES:DI-    Pointer to list.
  7203.             CS-    Node number of new current node.
  7204.  
  7205. Registers on exit:    DX:SI-    Returned pointing at selected node.
  7206.                 NIL if the list is empty.  Points at the
  7207.                 last node in the list if the value in CX
  7208.                 is greater than the number of nodes in the
  7209.                 list.
  7210.  
  7211. Flags on return:    Carry set if the list was empty.
  7212.  
  7213. Examples of Usage:
  7214.  
  7215.             les    di, MyList
  7216.             mov    cx, NodeNum
  7217.             SetCur
  7218.             jc    EmptyList
  7219.  
  7220. Description:
  7221.  
  7222. SetCur locates the specified node in the list and sets CurrentNode to the
  7223. address of that node. It also returns a pointer to that node in DX:SI.
  7224. If CX is greater than the number of nodes in the list (or zero) then
  7225. SetCur sets CurrentNode to the last node in the list.  If the list is
  7226. empty, SetCur returns NIL in DX:SI and returns with the carry flag set.
  7227.  
  7228. Include:    stdlib.a or lists.a
  7229.  
  7230.  
  7231.  
  7232. Routine:  Insert (m)
  7233. --------------------
  7234.  
  7235. Author:                  Randall Hyde
  7236.  
  7237. Category:                 List Manipulation
  7238.  
  7239. Registers on entry:       ES:DI-    Pointer to list.
  7240.             DX:SI-    Address of node to insert (Insert)
  7241.             DX:SI-    Pointer to data block to create node from
  7242.                 (Insertm).
  7243.             CX-    Number of node to insert DX:SI in front of;
  7244.                 Note that the list is one-based.  That is,
  7245.                 the number of the first node in the list is
  7246.                 one.  Zero corresponds to the last node in
  7247.                 the list.
  7248.  
  7249.  
  7250. Flags on return:    Carry set if malloc error occurs (Insertm only).
  7251.  
  7252. Examples of Usage:
  7253.  
  7254.             les    di, MyList
  7255.             ldxi    NewNode
  7256.             mov    cx, 5
  7257.             Insert            ;Inserts before Node #5.
  7258.  
  7259. ; The following example builds a new node on the heap from the data at
  7260. ; location "RawData" and inserts this before node #5 in MyList.
  7261.  
  7262.             les    di, MyList
  7263.             ldxi    RawData
  7264.             mov    cx, 5
  7265.             Insertm
  7266.             jc    MallocError
  7267.  
  7268. Description:
  7269.  
  7270. Insert(m) inserts a new node before a specified node in the list.  The node to
  7271. insert in front of is specified by the value in the CX register.  The first
  7272. node in the list is node #1, the second is node #2, etc.  If the value in
  7273. CX is greater than the number of nodes in the list (in particular, if CX
  7274. contains zero, which gets treated like 65,536) then Insert(m) appends the
  7275. new node to the end of the list.
  7276.  
  7277. Insertm allocates a new node on the heap (DX:SI points at the data fields
  7278. for the node).  If a malloc error occurs, Insertm returns the carry flag
  7279. set.
  7280.  
  7281. CurrentNode gets set to the newly inserted node.
  7282.  
  7283. Include:    stdlib.a or lists.a
  7284.  
  7285.  
  7286.  
  7287. Routine:  Append (m)
  7288. --------------------
  7289.  
  7290. Author:                  Randall Hyde
  7291.  
  7292. Category:                 List Manipulation
  7293.  
  7294. Registers on entry:       ES:DI-    Pointer to list.
  7295.             DX:SI-    Address of node to insert (Append)
  7296.             DX:SI-    Pointer to data block to create node from
  7297.                 (Appendm).
  7298.             CX-    Number of node to insert DX:SI after;
  7299.                 Note that the list is one-based.  That is,
  7300.                 the number of the first node in the list is
  7301.                 one.  Zero corresponds to the last node in
  7302.                 the list.
  7303.  
  7304.  
  7305. Flags on return:    Carry set if malloc error occurs (Appendm only).
  7306.  
  7307. Examples of Usage:
  7308.  
  7309.             les    di, MyList
  7310.             ldxi    NewNode
  7311.             mov    cx, 5
  7312.             Append            ;Inserts after Node #5.
  7313.  
  7314. ; The following example builds a new node on the heap from the data at
  7315. ; location "RawData" and inserts this after node #5 in MyList.
  7316.  
  7317.             les    di, MyList
  7318.             ldxi    RawData
  7319.             mov    cx, 5
  7320.             Appendm
  7321.             jc    MallocError
  7322.  
  7323. Description:
  7324.  
  7325. Append(m) inserts a new node after a specified node in the list.  The node to
  7326. insert in front of is specified by the value in the CX register.  The first
  7327. node in the list is node #1, the second is node #2, etc.  If the value in
  7328. CX is greater than the number of nodes in the list (in particular, if CX
  7329. contains zero, which gets treated like 65,536) then Insert(m) appends the
  7330. new node to the end of the list.
  7331.  
  7332. Appendm allocates a new node on the heap (DX:SI points at the data fields
  7333. for the node).  If a malloc error occurs, Appendm returns the carry flag
  7334. set.
  7335.  
  7336. CurrentNode gets set to the newly inserted node.
  7337.  
  7338. Include:    stdlib.a or lists.a
  7339.  
  7340.  
  7341.  
  7342.  
  7343. Routine:  Remove
  7344. ----------------
  7345.  
  7346. Author:                  Randall Hyde
  7347.  
  7348. Category:                 List Manipulation
  7349.  
  7350. Registers on entry:       ES:DI-    Pointer to list.
  7351.             CX-    # of node to delete from list.
  7352.  
  7353. Registers on exit:    DX:SI-    Points at node removed from list (NIL if
  7354.                 no such node).
  7355.  
  7356. Flags on return:    Carry set if the list was empty.
  7357.  
  7358. Examples of Usage:
  7359.  
  7360.             les    di, MyList
  7361.             mov    cx, NodeNumbr
  7362.             Remove
  7363.             jc    EmptyList
  7364.  
  7365. Description:
  7366.  
  7367. Remove removes the specified node (given by CX) from the list
  7368. and returns a pointer to this node in DX:SI.  If the list was empty, Remove
  7369. returns NIL in DX:SI and sets the carry flag.
  7370.  
  7371. This routine modifies CurrentNode so that it points at the next item in the
  7372. list (the node normally following the current node).  If there is no such
  7373. node (i.e., CurrentNode pointed at the last node in the list upon calling
  7374. Remove) then this routine stores the value of the *previous* node into
  7375. CurrentNode.  If you use this routine to delete the last node in the list,
  7376. it sets CurrentNode to NIL before leaving.
  7377.  
  7378. Include:    stdlib.a or lists.a
  7379.  
  7380.